为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定义行为

马拉车

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=100100;
 9 int n,siz;
10 char ch[maxn]={};
11 char ch1[maxn*2]={};
12 int p[maxn*2]={};
13 void fir(){
14     siz=n*2+2;
15     ch1[0]='$';ch1[1]='#';
16     for(int i=1;i<=n;i++)ch1[i*2]=ch[i-1],ch1[i*2+1]='#';
17     ch1[siz]='\0';
18 }
19 int Manacher(){
20     fir();int x=0,j=0,ans=0;
21     for(int i=1;i<siz;i++){
22         if(x+j>i)p[i]=min(x+j-i+1,p[x*2-i]);
23         else p[i]=0;
24         while(ch1[i+p[i]]==ch1[i-p[i]])p[i]++;
25         if(i+p[i]-1>x+j)x=i,j=p[i]-1;
26         if(p[i]>ans)ans=p[i];
27         //cout<<i<<ch1[i]<<p[i]<<endl;
28     }
29     return ans-1;
30 }
31 int main(){
32     int T;scanf("%d",&T);
33     while(T-->0){//ch[i],ch1[i],p[i]似乎都不用清空,因为所有的用之前都已经被清一次了。
34         scanf("%s",ch);n=strlen(ch);
35         int ma=Manacher();
36         printf("%d\n",ma);
37     }
38     return 0;
39 }

Manacher

kmp

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=100100;
 9 int cn,sn;//模式串和主串的大小
10 char ch[maxn]={};//模式串
11 char st[maxn]={};//主串
12 int nex[maxn]={};
13 void kmp(){
14     int j=-1,i=0;
15     nex[0]=-1;
16     while(i<cn){
17         if(j==-1||ch[i]==ch[j])nex[++i]=++j;
18         else j=nex[j];
19     }
20 }
21 int get_id(){//在主串中第一次出现的位置
22     int i=0,j=0;
23     while(i<sn&&j<cn){
24         if(j==-1||ch[j]==st[i]){i++;j++;}
25         else j=nex[j];
26     }
27     if(j==cn)return i-cn;
28     else return -1;
29 }
30 int get_count(){//在主串中出现的次数
31     int i,j=0,cnt=0;
32     for(i=0;i<sn;i++){
33         while(j>0&&st[i]!=ch[j]) j=nex[j];
34         if(st[i]==ch[j])j++;
35         if(j==cn){cnt++;j=nex[j];}
36     }
37     return cnt;
38 }
39 int main(){
40     int T;scanf("%d",&T);
41     while(T-->0){
42         scanf("%s",ch);cn=strlen(ch);
43         scanf("%s",st);sn=strlen(st);
44         kmp();
45         printf("%d %d\n",get_id(),get_count());
46     }
47     return 0;
48 }

kmp

ac自动机(在poj2222提交的时候wa了好几次后来发现没有清空,而且这次重新打发现了自己之前写的漏洞。。。)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=10100;
 9 int n,siz;
10 char ch[60]={};
11 char str[maxn*100]={};
12 struct trie{
13     int sig[26];
14     int cnt;
15     int vis;
16     int fail;
17 }t[maxn*60];int tot=0;
18 int q[maxn*60]={};int head=0,tail=0;
19 void fir(){
20     tot=0;memset(t,0,sizeof(t));//memset(q,0,sizeof(q));
21 }
22 void init(int x,int j){
23     if(j>siz-1){ t[x].cnt++; return; }
24     int z=ch[j]-'a';
25     if(!t[x].sig[z])t[x].sig[z]=++tot;
26     init(t[x].sig[z],j+1);
27 }
28 void build_fail(){
29     int head=0,tail=0,x,y,f;q[0]=0;
30     while(head<=tail){
31         x=q[head++];
32         for(int i=0;i<26;i++)
33             if(t[x].sig[i]){
34                 y=t[x].sig[i];
35                 if(x){
36                     f=t[x].fail;
37                     while((!t[f].sig[i])&&f)
38                         f=t[f].fail;
39                     t[y].fail=t[f].sig[i];
40                 }q[++tail]=y;
41             }
42     }
43 }
44 int get_num(){//字符串中包含的单词数量,重复的不记录,
45     //如果单词x在字符串中出现一次而在单词表中有两个则ans+2
46     //在字符串中出现两次而单词表中有一个则ans+1
47     int ans=0,x=0,y,z;
48     for(int i=0;i<siz;i++){
49         z=str[i]-'a';
50         while((!t[x].sig[z])&&x)
51             x=t[x].fail;
52         x=t[x].sig[z];y=x;
53         while(y&&(!t[y].vis)){//保证了每个结尾只访问一次
54             ans+=t[y].cnt;
55             t[y].vis=1;t[y].cnt=0;
56             y=t[y].fail;
57         }
58     }
59     return ans;
60 }
61 int main(){
62     int T;scanf("%d",&T);
63     while(T-->0){
64         fir();
65         scanf("%d",&n);
66         for(int i=1;i<=n;i++){scanf("%s",ch);siz=strlen(ch);init(0,0);}
67         build_fail();
68         scanf("%s",str);siz=strlen(str);
69         printf("%d\n",get_num());
70     }
71     return 0;
72 }

AC自动机

后缀数组 每次都l=<<2然后调错,我大概是个zz。一定要分清楚*2和<<1啊

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn=100010;
 9 const int pl=50;
10 int siz;
11 char ch[maxn+pl]={};
12 int p[maxn+pl]={},sa[maxn+pl]={},rk[maxn+pl]={};
13 int cnt[maxn+pl]={},temp[maxn+pl]={},height[maxn+pl]={};
14 bool equ(int x,int y,int l){return rk[x]==rk[y]&&rk[x+l]==rk[y+l];}
15 void SA(){
16     for(int i=1;i<=siz;i++)sa[i]=i,rk[i]=ch[i];
17     for(int i,sig=255,pos=0,l=0;pos<siz;sig=pos){
18         pos=0;
19         for(i=siz-l+1;i<=siz;i++)p[++pos]=i;
20         for(i=1;i<=siz;i++)if(sa[i]>l)p[++pos]=sa[i]-l;
21         for(i=1;i<=sig;i++)cnt[i]=0;
22         for(i=1;i<=siz;i++)cnt[rk[p[i]]]++;
23         for(i=1;i<=sig;i++)cnt[i]+=cnt[i-1];
24         for(i=siz;i>0;i--) sa[cnt[rk[p[i]]]--]=p[i];
25         pos=0;
26         for(i=1;i<=siz;i++){
27             if(equ(sa[i],sa[i-1],l))temp[sa[i]]=pos;
28             else temp[sa[i]]=++pos;
29         }
30         for(i=1;i<=siz;i++)rk[i]=temp[i];
31         if(!l)l=1;
32         else l<<=1;
33     }
34     int j=0;
35     for(int i=1;i<=siz;i++){
36         if(rk[i]==1){j=0;continue;}
37         if(j)j--;
38         while(ch[i+j]==ch[sa[rk[i]-1]+j])j++;
39         height[rk[i]]=j;
40     }
41 }
42 int main(){
43     scanf("%s",ch+1);
44     siz=strlen(ch+1);
45     SA();
46     for(int i=1;i<=siz;i++)printf("%d ",sa[i]);
47     cout<<endl;
48     for(int i=2;i<=siz;i++)printf("%d ",height[i]);
49     cout<<endl;
50     return 0;
51 }

后缀数组

后缀自动机,相对于它的名气好写。但是有时候还是会在犯zz错误 这里的代码copy过来了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<map>
 7 using namespace std;
 8 const int maxn=100010;
 9 char ch1[maxn]={},ch2[maxn]={};
10 int siz1,siz2;
11 struct nod{
12     int sig[26];
13     int f,len;
14 }t[maxn*2];int tot=1,la=1;
15 void add(int z){
16     int x=++tot;int i=la;
17     t[x].len=t[la].len+1;
18     for(;i&&!t[i].sig[z];i=t[i].f)
19         t[i].sig[z]=x;
20     if(!i)t[x].f=1;
21     else{
22         int p=t[i].sig[z];
23         if(t[p].len==t[i].len+1)t[x].f=p;
24         else{
25             int y=++tot;
26             t[y]=t[p];t[y].len=t[i].len+1;
27             t[x].f=t[p].f=y;
28             for(;i&&t[i].sig[z]==p;i=t[i].f){
29                 t[i].sig[z]=y;
30             }
31         }
32     }
33     la=x;
34 }
35 int main(){
36     memset(t,0,sizeof(t));
37     scanf("%s",ch1+1);
38     scanf("%s",ch2+1);
39     siz1=strlen(ch1+1);
40     siz2=strlen(ch2+1);
41     for(int i=1;i<=siz1;i++)add(int(ch1[i]-'a'));
42     int ans=0,j=1,tmp=0;
43     for(int i=1;i<=siz2;i++){
44         int z=ch2[i]-'a';
45         if(t[j].sig[z]){j=t[j].sig[z];tmp++;}
46         else{
47             while(j&&!t[j].sig[z])
48                 j=t[j].f;
49             if(!j){j=1;tmp=0;}
50             else {tmp=t[j].len+1;j=t[j].sig[z];}
51         }
52         if(tmp>ans)ans=tmp;
53     }printf("%d\n",ans);
54     return 0;
55 }

SAM

转载于:https://www.cnblogs.com/137shoebills/p/8516404.html

字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机相关推荐

  1. bzoj2946 [Poi2000]公共串(后缀数组 || 后缀自动机)

    bzoj2946 [Poi2000]公共串 原题地址:http://www.lydsy.com/JudgeOnline/problem.php?id=2946 题意: 给出几个由小写字母构成的单词,求 ...

  2. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分...

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  3. 后缀数组求最长重复子串

    问题描述 给定一个字符串,求出其最长重复子串 例如:abcdabcd 最长重复子串是 abcd,最长重复子串可以重叠 例如:abcdabcda,这时最长重复子串是 abcda,中间的 a 是被重叠的. ...

  4. 五分钟搞懂后缀数组!

    为什么学后缀数组 后缀数组是一个比较强大的处理字符串的算法,是有关字符串的基础算法,所以必须掌握.  学会后缀自动机(SAM)就不用学后缀数组(SA)了?不,虽然SAM看起来更为强大和全面,但是有些S ...

  5. 后缀数组及lcp学习笔记

    模板题 给出一个字符串,输出排名为 iii 的后缀的编号,i=1,2,3,...ni=1,2,3,...ni=1,2,3,...n. 一种求法 想当年我字符串题用哈希水遍天下=.= 可以二分 lcpl ...

  6. 五分钟搞懂后缀数组!后缀数组解析以及应用(附详解代码)

    为什么学后缀数组 后缀数组是一个比较强大的处理字符串的算法,是有关字符串的基础算法,所以必须掌握. 学会后缀自动机(SAM)就不用学后缀数组(SA)了?不,虽然SAM看起来更为强大和全面,但是有些SA ...

  7. 后缀树和后缀数组的一些资料收集

    后缀树(Suffix tree)是一种数据结构,能快速解决很多关于字符串的问题.后缀树的概念最早由Weiner 于1973年提出,既而由McCreight 在1976年和Ukkonen在1992年和1 ...

  8. 算法竞赛进阶指南——后缀数组

    后缀数组 后缀数组 (SA) 是一种重要的数据结构,通常使用倍增或者DC3算法实现,这超出了我们的讨论范围. 在本题中,我们希望使用快排.Hash与二分实现一个简单的O(nlog2n)的后缀数组求法. ...

  9. 后缀数组(倍增)学习记录,我尽可能详细的讲了

    后缀数组(倍增) 后缀数组 后缀数组能干什么 一些基本概念 那么到底怎么排序呢? 倍增排序 具体执行排序呢? 基数排序 关于排序的桶 关于桶排序在字符串倍增中的嵌入 具体改执行的排序事情 倍增排序的代 ...

  10. DC3算法(后缀数组生成)

    文章目录 后缀数组是什么? 后缀数组的地位 后缀数组的生成 基数排序 概念 算法流程 生成后缀数组 得到S12类的排名 解释 代码 后缀数组是什么? 如果我要对数组排序的话,按字符串的字典序来排,这个 ...

最新文章

  1. PowerDesigner 使用的一些技巧(转)
  2. Windows之Chocolatey:windows下的apt-get即Chocolatey简介、安装、使用方法之详细攻略
  3. [flutter专题]详解AppBar小部件
  4. 趣学算法之哥德巴赫猜想的实现
  5. 一个人的旅行(HDU-2066)
  6. Linux下mongodb安装及数据导入导出教程
  7. Fogengine概述
  8. Android唤醒屏幕
  9. 【答题卡识别】基于matlab GUI hough变换答题卡判定与成绩统计(带面板)【含Matlab源码 1017期】
  10. 计算机应用在服务业的发展,饮食服务业计算机应用的现状与未来
  11. java 视频比特率_java – 为MediaCodec设置的有效比特率是多少
  12. wifi+遥控器+android,基于安卓手机wifi的智能遥控器设计
  13. 什么是VHDL?一文带你了解VHDL语言
  14. Android Studio中Intent的用法3-2
  15. 一周疫情对行业影响观察 | 中国资产或成避险资产;亚太旅游零售业呼吁政府财政支持...
  16. OpenKruise :SidecarSet 助力 Mesh 容器热升级,TCP的三次握手、四次挥手
  17. 影视广告创意与制作(四)
  18. 蚁群算法 python
  19. Java发送邮件链接实现登录注册
  20. Unity Application Block 1.2 学习笔记(zhuan)

热门文章

  1. 苹果mac屏幕录像软件:ScreenFlow
  2. 在苹果Mac上如何指定发送邮件的时间?
  3. PowerPhotos:Mac照片库管理软件
  4. 解压软件Bandizip Archiver for mac
  5. Mac上如何重启或结束Finder进程?
  6. Docker 开篇 1 | 树莓派中搭建Docker
  7. Nexus-NuGet私有仓库服务搭建(一)
  8. RecyclerView的基础用法
  9. 用php实现遍历目录
  10. android 文件加密源码