字符串算法整理

kmp 算法

先让模式串匹配自己,得出 $next$ 数组(实际是某段字符串的最长公共前后缀),在匹配时跳过多余的错误字符。

模板

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int nxt[1000010];
 8 int la,lb,j; 
 9 char a[1000010],b[1000010];
10 
11 int main(){
12     scanf("%s",a+1);
13     scanf("%s",b+1);
14     la=strlen(a+1);
15     lb=strlen(b+1);
16     for (int i=2;i<=lb;i++){     
17         while(j&&b[i]!=b[j+1])j=nxt[j];//不断跳找是否有其他的nxt 
18         if(b[j+1]==b[i])j++;//在原来基础上扩展 
19         nxt[i]=j;
20     }
21     j=0;
22     for(int i=1;i<=la;i++){
23         while(j>0&&b[j+1]!=a[i])
24         j=nxt[j];//失配就跳 
25         if(b[j+1]==a[i]) 
26         j++;//能匹配 
27         if (j==lb){
28             printf("%d\n",i-lb+1);//读位置 
29             j=nxt[j];
30         }
31     }
32     for (int i=1;i<=lb;i++)
33         printf("%d ",nxt[i]);
34     return 0;
35 }
View Code

manacher 算法

线性时间寻找回文串,利用对称性类似于单调扩展(不知道单调扩展是什么东西

模板

code:

 1 #include<cstdio>
 2 #include<iostream> 
 3 
 4 using namespace std;
 5 
 6 const int N=11000007;
 7 char ch[N<<1];
 8 int p[N<<1];
 9 int cnt,ans=-0x7fffffff;
10 
11 void scanFChar(){
12     cnt=1;
13     ch[0]='~',ch[cnt]='|';
14     char c=getchar();
15     while(c>='a'&&c<='z'){
16         ch[++cnt]=c;ch[++cnt]='|';
17         c=getchar();
18     }
19 }//读入 
20 
21 int main(){
22     scanFChar();
23     //r:最右回文串的右边界,mid:最右回文串的回文中心 
24     for(int i=1,r=0,mid=0;i<=cnt;i++){
25         if(i<=r) p[i]=min(p[(mid<<1)-i],r-i+1); 
26         while(ch[i-p[i]]==ch[i+p[i]]) p[i]++;
27         if(p[i]+i>r) r=p[i]+i-1,mid=i;
28         ans=max(ans,p[i]);//最大的串场就是回文半径长减1(因为有'|'的加入) 
29     }
30     printf("%d",ans-1);
31     return 0;    
32 }
View Code

Trie

通过建立公共前缀链构成树,以空间换时间

模板

code:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<cstring>
 6 
 7 using namespace std;
 8 
 9 const int N=5e6+10;
10 int n,m;
11 char ch[55];
12 bool vis[N],tot[N];
13 int t[N][27],cnt,root;
14 
15 void insert(char ch[]){
16     int len=strlen(ch);
17     root=0;
18     for(int i=0;i<=len-1;i++){
19         int k=ch[i]-'a';
20         if(!t[root][k]) t[root][k]=++cnt;
21         root=t[root][k];//向下走建字符链 
22     }
23     vis[root]=1;
24 }
25 
26 int fiNd(char ch[]){
27     int len=strlen(ch);
28     root=0;
29     for(int i=0;i<=len-1;i++){
30         int k=ch[i]-'a';
31         if(!t[root][k]) return 0;//没有这个字符 
32         root=t[root][k];//不断向下爬 
33     }
34     if(!vis[root]) return 0;//有前缀无单词 
35     else{
36         if(!tot[root]){
37             tot[root]=1;
38             return 1;//第一次查询,打标记 
39         } 
40         else return 2;
41     }
42 }
43 
44 int main(){
45     scanf("%d",&n);
46     getchar();
47     while(n--){
48         scanf("%s",ch);
49         insert(ch);
50     }
51     scanf("%d",&m);
52     getchar();
53     while(m--){
54         scanf("%s",ch);
55         if(fiNd(ch)==1) printf("OK");
56         else if(fiNd(ch)==2) printf("REPEAT");
57         else if(fiNd(ch)==0) printf("WRONG");
58         printf("\n");
59     }
60     return 0;
61 }
View Code

 AC 自动机

 

PAM 回文自动机

trie 树上挂回文串,还有一点 fail 指针提速

模板

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 
 6 using namespace std;
 7 
 8 const int N=5e5+10;
 9 char ch[N];
10 int t[N][27],len[N],fail[N],num[N],c,ans,pos,last,x;
11 int tot=1;
12 
13 int geTFail(int pos,int x){
14     while(x-len[pos]-1<0||ch[x-len[pos]-1]!=ch[x]) pos=fail[pos];
15     return pos; 
16 }
17 
18 int main(){
19     scanf("%s",ch);
20     int n=strlen(ch);
21     fail[0]=1;len[1]=-1;
22     for(int i=0;i<n;i++){
23         if(i>=1) ch[i]=(ch[i]+last-97)%26+97;
24         pos=geTFail(x,i);
25         if(!t[pos][ch[i]-'a']){
26             fail[++tot]=t[geTFail(fail[pos],i)][ch[i]-'a'];
27             t[pos][ch[i]-'a']=tot;
28             len[tot]=len[pos]+2;
29             num[tot]=num[fail[tot]]+1;
30         }
31         x=t[pos][ch[i]-'a'];
32         last=num[x];
33         printf("%d ",last);
34     }
35     return 0;
36 } 
View Code
posted @ 2023-07-05 20:47  々Trouvaille々  阅读(11)  评论(0)    收藏  举报