有关字符串的算法有点多,打算一个一个慢慢来。
KMP
这是一个十分神奇的字符串匹配算法,详细过程可在网上搜索。为什么说KMP神奇呢?因为它困扰了我很久很久。days?no,years!
我就是对这个算法始终有点模糊,学了忘,忘了学,今天又学了一遍有了印象,也写出来了模板,但是可能过了几天又忘了,这种感觉很难讲,我觉得应该要始终备着一个模拟数据来每次模拟一遍,要不然我会对这个算法一直有阴影的。
例题:GDOI2017 房屋购置
这道题是对KMP有阴影的另一个原因……,其实就是道裸题,但是我永远不会忘记那一天的痛~
#include <bits/stdc++.h> #define mp make_pair using namespace std; typedef long long ll; inline int read(){int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} const int maxn = 400005; const int INF = 0x3f3f3f3f; char sss[21][maxn],s1[maxn],s2[maxn]; int a[21],p[maxn]; int n,m,i,len_s1,j,k,l,len_s2,y,z; int main() { n=read(); m=read(); for (i=1;i<=n;i++) { scanf("%s",sss[i]+1); a[i]=strlen(sss[i]+1); } while(m--) { scanf("%s%s",s1+1,s2+1); len_s1=strlen(s1+1); len_s2=strlen(s2+1); j=0; for (i=2;i<=len_s1;i++) { while (s1[i]!=s1[j+1] && j) j=p[j]; p[i]=(s1[i]==s1[j+1])?++j:j; } for (k=1;k<=n;k++) { j=0; for (i=1;i<=a[k];i++) { if (sss[k][i]=='#') continue; while (s1[j+1]!=sss[k][i] && j) j=p[j]; if (s1[j+1]==sss[k][i]) { j++; if (j!=len_s1) continue; y=i; l=len_s2; while (l) { if (sss[k][y]!='#') sss[k][y]=s2[l],l--; y--; } l+=len_s1-len_s2; while (l) { if (sss[k][y]!='#') sss[k][y]='#',l--; y--; } j=0; } } } } for (i=1;i<=n;i++) { for (j=1;j<=a[i];j++) if (sss[i][j]!='#') cout<<sss[i][j]; cout<<endl; } }
Manacher算法
回文串算法,这个就比较好写,详细过程可在网上搜索。
Codeforces 1326D1 or D2
a+b,a是前缀,b是后缀
1 若a为空或b为空,则直接做一次回文串算法,注意看是否符合前缀或后缀
2 若a和b都不为空,则先字符串前后进行依次匹配,直到不能匹配时,把中间的字符串再取出来重复1的操作
#include <bits/stdc++.h> #define mp make_pair using namespace std; typedef long long ll; inline int read(){int s=0,w=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w;} const int maxn = 4000005; const int INF = 0x3f3f3f3f; int i,j,t,len,len1,len2,Len[maxn]; string ss,ans1,ans2,s; char tmp[maxn]; void Manacher(string s) { int i,mx=0,mid=0,x,Left,Right,len; len1=len2=0; tmp[0]='@'; tmp[1]='#'; len=s.size(); for (i=0;i<=2*len+3;i++)Len[i]=0; for (i=1;i<=len;i++) { tmp[2*i]=s[i-1]; tmp[2*i+1]='#'; } tmp[2*len+2]='