当前位置: 首页 > wzjs >正文

成都网站建设服务有什么aso优化吧

成都网站建设服务有什么,aso优化吧,网站建设现状,天津哪里做网站最好问题描述 依依是一个住在海边小镇的女孩,她的朋友们分散在世界的各个角落。他们有一个特殊的传递信息的方式,那就是通过海洋传递瓶中信。每个瓶中信里,都装着一串由小写英文字母组成的信息,代表一个友情的密码。 这个夏天&#…

问题描述

依依是一个住在海边小镇的女孩,她的朋友们分散在世界的各个角落。他们有一个特殊的传递信息的方式,那就是通过海洋传递瓶中信。每个瓶中信里,都装着一串由小写英文字母组成的信息,代表一个友情的密码。

这个夏天,依依在海滩上捡到了 N 个瓶中信,每个瓶中信里都有一条由小写英文字符组成的信息,这些信息分别来自她的 N 个朋友。我们记第 ii 个朋友的信息为 Si,其中 i=1,2,...,N。

为了找出与自己最有缘分的朋友,依依决定比较这些信息的相似度。这里的"相似度"指的是两条信息从头开始,最长能够匹配的字符数量。

注意,依依并不想比较一条信息与它自身的相似度。

现在,依依希望你能帮助她找出对于每条信息 Si,哪条信息与其最相似,即从开头开始,最长能连续匹配的字符的数量是多少。

输入格式

输入的第一行包含一个整数 NN(1≤N≤104)。

接下来的 NN 行,每行包含一个由小写字符构成的字符串 SiSi​,表示小蓝的一个朋友在信封里刻写的信息。保证

输出格式

输出共 N行,对于每条信息Si​,输出一个整数,表示与 Si​ 最接近的信息的最长公共前缀的长度。

样例输入

3
abc
ab
bc

 

样例输出

2
2
0

解题代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
string s[N];//存储n个信息s
int tire[N][27],idx=2,cnt[N];void insert(string a){  //生成一个tire树,把所有s都插入到树中int n=a.length()-1;//在 C++ 的 std::string 中,a[i] 不会自动包含 '\0'。int x=1;for(int i=1;i<=n;i++){if(!tire[x][a[i]-'a']) tire[x][a[i]-'a']=idx++; //如果不存在的话就创建这个节点x=tire[x][a[i]-'a'];  //这个是让x指向当前节点cnt[x]++;//让每个走过当前节点都用cnt记录下来并自加//这个是关键,当cnt[x]>1的时候说明这个节点至少有两个字符串是走过这里的}
}int check(string a){int n=a.length()-1;int x=1;int ans=0;for(int i=1;i<=n;i++){x=tire[x][a[i]-'a'];if(cnt[x]!=1){//当cnt[x]不等于1的时候说明此时的s[i]肯定有一个s的前s[t]和s[i]的前i是相同的ans=i;//当存在s[t]和s[i]相同的时候就让ans=i,i是相同的字符的个数}else break;//如果cnt[x]==1说明没有与之匹配的串了,直接退出返回当前的ans就行}return ans;
}
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>s[i];s[i]='0'+s[i];insert(s[i]);}for(int i=1;i<=n;i++){cout<<check(s[i])<<"\n";}return 0;
}

解题思路:

  1. 字典树(Trie)

    • 使用字典树存储所有字符串的前缀信息。

    • 字典树的每个节点表示一个字符,从根节点到某个节点的路径表示一个前缀。

  2. 统计前缀出现次数

    • 在插入字符串时,记录每个节点被访问的次数(cnt[x]++)。

    • 如果某个节点的 cnt[x] > 1,说明至少有两个字符串共享这个前缀。

  3. 查询最长公共前缀

    • 对于每个字符串,从根节点开始遍历字典树,找到最深的满足 cnt[x] > 1 的节点。

    • 这个节点的深度就是该字符串与其他字符串的最长公共前缀长度。


为什么将 cnt[x]++ 写在 for 循环里面?

在字典树算法中,cnt[x]++ 的作用是记录每个节点被访问的次数。以下是详细解释:


1. cnt[x]++ 的作用

  • cnt[x]:表示从根节点到节点 xx 的路径所表示的前缀被多少个字符串共享。

  • cnt[x]++:每当一个字符串经过节点 x 时,cnt[x] 增加 1。


2. 为什么写在 for 循环里面?

  • 插入字符串时

    • 在插入字符串的过程中,每经过一个节点 x,都需要更新 cnt[x]

    • 这是因为每个节点都代表一个前缀,cnt[x] 记录了有多少个字符串共享这个前缀。

  • 查询最长公共前缀时

    • 在查询过程中,cnt[x] 用于判断当前前缀是否被多个字符串共享。

    • 如果 cnt[x] > 1,说明当前前缀被至少两个字符串共享。


3. 示例分析

假设有以下字符串:

abc
ab
a

插入过程

  1. 插入 abc

    • 经过节点 acnt[a] = 1

    • 经过节点 bcnt[ab] = 1

    • 经过节点 ccnt[abc] = 1

  2. 插入 ab

    • 经过节点 acnt[a] = 2

    • 经过节点 bcnt[ab] = 2

  3. 插入 a

    • 经过节点 acnt[a] = 3

查询过程

  1. 查询 abc

    • 节点 acnt[a] = 3 > 1,匹配长度 = 1。

    • 节点 bcnt[ab] = 2 > 1,匹配长度 = 2。

    • 节点 ccnt[abc] = 1,停止。

    • 最长公共前缀长度 = 2。

  2. 查询 ab

    • 节点 acnt[a] = 3 > 1,匹配长度 = 1。

    • 节点 bcnt[ab] = 2 > 1,匹配长度 = 2。

    • 最长公共前缀长度 = 2。

  3. 查询 a

    • 节点 acnt[a] = 3 > 1,匹配长度 = 1。

    • 最长公共前缀长度 = 1。

代码说明:

第一种实现

void insert(string a) {int n = a.length() - 1;int x = 1;for (int i = 1; i <= n; i++) {if (!tire[x][a[i] - 'a']) tire[x][a[i] - 'a'] = idx++;x = tire[x][a[i] - 'a'];cnt[x]++;}
}

特点:

  1. 字符串下标从 1 开始

    • 字符串 a 的下标从 1 开始,a[0] 被忽略。

    • 这是因为在主函数中,字符串被修改为 s[i] = '0' + s[i],即在字符串前面添加了一个字符 '0',使得有效字符从下标 1 开始。

  2. 循环范围

    • 循环从 i = 1 到 i = n,其中 n = a.length() - 1

    • 这样可以正确处理字符串的有效部分。


第二种实现

void insert(string a) {int x = 1;for (int i = 0; a[i]; i++) {if (!tire[x][a[i] - 'a']) tire[x][a[i] - 'a'] = idx++;x = tire[x][a[i] - 'a'];cnt[x]++;}
}

特点

  1. 字符串下标从 0 开始

    • 字符串 a 的下标从 0 开始,a[0] 是第一个字符。

    • 这与主函数中对字符串的处理方式不一致。

  2. 循环范围

    • 循环从 i = 0 开始,直到 a[i] 为 '\0'(字符串结束符)。

    • 这种写法适用于标准的 C 风格字符串(以 '\0' 结尾),但在 C++ 的 std::string 中,a[i] 不会自动包含 '\0'

为什么不能使用第二种实现?

  1. 字符串下标不一致

    • 在主函数中,字符串被修改为 s[i] = '0' + s[i],即在字符串前面添加了一个字符 '0',使得有效字符从下标 1 开始。

    • 如果使用第二种实现,a[0] 会被错误地当作有效字符处理,导致 Trie 树插入错误。

  2. 循环范围问题

    • 第二种实现假设字符串以 '\0' 结尾,但在 C++ 的 std::string 中,a[i] 不会自动包含 '\0'

    • 如果字符串中没有 '\0',循环会越界访问,导致未定义行为。

  3. 逻辑错误

    • 第二种实现无法正确处理主函数中对字符串的修改(添加了前缀字符 '0')。

    • 这会导致 Trie 树中插入的字符串与实际字符串不一致,影响后续的查询操作。

字典树(Trie)来解决问题,但它们的应用场景具体实现有所不同。以下是详细对比:


题目 1:最长公共前缀问题(依依的瓶中信)

问题描述

  • 给定 N 个字符串,对于每个字符串 Si​,找到与其他字符串的最长公共前缀的长度。

代码特点

  • cnt[x]++ 写在 for 循环里面

    • 在插入字符串时,每经过一个节点 x,都会更新 cnt[x]

    • 目的是记录每个节点被多少个字符串共享,从而在查询时判断当前前缀是否被多个字符串共享。

核心逻辑

  • 插入时

    • 每经过一个节点 x,cnt[x]++,表示当前前缀被一个字符串共享。

  • 查询时

    • 遍历字符串的每个字符,找到最深的满足 cnt[x] > 1 的节点,其深度就是最长公共前缀的长度。


题目 2:判断是否有重复字符串

问题描述

  • 给定 N 个字符串,判断是否存在两个相同的字符串。

代码特点

  • cnt[x]++ 写在 for 循环外面

    • 在插入字符串时,cnt[x]++ 只在字符串的末尾节点执行。

    • 目的是记录每个字符串的末尾节点被访问的次数。

核心逻辑

  • 插入时

    • 在字符串的末尾节点 x,cnt[x]++,表示当前字符串被插入了一次。

  • 查询时

    • 遍历字符串的每个字符,找到末尾节点 x。

    • 如果 cnt[x] > 1,说明当前字符串被插入了多次,即存在重复字符串。


为什么 cnt[x]++ 的位置不同?

题目 1:最长公共前缀问题

  • 目标:统计每个前缀被多少个字符串共享。

  • 实现

    • 在插入时,每经过一个节点 x,cnt[x]++,表示当前前缀被一个字符串共享。

    • 这样可以在查询时,通过 cnt[x] 判断当前前缀是否被多个字符串共享。

题目 2:判断是否有重复字符串

  • 目标:判断是否存在两个相同的字符串。

  • 实现

    • 在插入时,只在字符串的末尾节点 x,cnt[x]++,表示当前字符串被插入了一次。

    • 这样可以在查询时,通过 cnt[x] 判断当前字符串是否被插入了多次。

总结

题目目标cnt[x]++ 位置作用
最长公共前缀问题找到与其他字符串的最长公共前缀for 循环里面记录每个前缀被多少个字符串共享
判断是否有重复字符串判断是否存在两个相同的字符串for 循环外面记录每个字符串的末尾节点被访问的次数

通过调整 cnt[x]++ 的位置,可以灵活地实现不同的功能。

 

 

 

 

http://www.dtcms.com/wzjs/128365.html

相关文章:

  • 西宁做网站哪家好百度推广后台登录页面
  • 哈什么网一个网站做ppt如何查询百度搜索关键词排名
  • 武汉今天新闻头条网络排名优化软件
  • 外贸自己做网站好不好营销咨询公司排名前十
  • 做静态网站网站页面分析作业
  • liferay做网站好吗广州seo效果
  • zencart网站时间问题晋江怎么交换友情链接
  • 专业网站模仿百度信息流怎么投放
  • 苏州房地产网站建设手机版百度一下
  • 丹阳网站建设方案网站推广的基本方法有哪些
  • 网站编译成dll专业的网站优化公司排名
  • 网站建设项目方案网页模板素材
  • 微信网站开发js框架b站推广网站mmm
  • 外贸公司网站制作价格真正免费建站
  • 网上做广告的网站云搜索app
  • 做网站靠广告一年赚多少钱免费b站推广
  • 外贸网站建设 深圳阳西网站seo
  • wordpress bbs吗seo网站推广优化论文
  • 惠州市建设公司网站百度网站推广关键词怎么查
  • 网站做的不满意网站seo在线优化
  • 私人公司怎么做网站网络整合营销策划书
  • 做外卖有哪些网站网络营销推广方式案例
  • 最大郑州网站建设公司上海知名网站制作公司
  • 利用excel做填报网站爱站网seo查询
  • 2018wordpress主题seo优化排名百度教程
  • 网页制作素材网站设计网站模板
  • 用vs2012怎么做网站游戏代理平台一天结一次
  • wordpress更新css中山seo关键词
  • 存量权益登记在哪个网站上做如何做网络推广运营
  • 北京网站建设开发公司天津百度网站快速排名