1.kmp
/* kmp */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define MAXN 1024//字符串长度 int _next[MAXN]; void GetNext(char t[]){//求next数组 int j,k,len; j=0;//从0开始,首先求_next[1] k=-1;//比较指针 _next[0]=-1;//初始值-1 len=strlen(t); while(j<len){ if(k==-1||t[j]==t[k]){//指针到头了,或者相等 ++j; ++k; _next[j]=k;//此句可由优化替代 /*优化(求匹配位置时可用) if(t[j]!=t[k])_next[j]=k; else _next[j]=_next[k]; //*/ } else k=_next[k]; } } int KMPIndex(char s[],char t[]){//求子串首次出现在主串中的位置 int i,j,lens,lent; i=j=0; lens=strlen(s); lent=strlen(t); while(i<lens&&j<lent){ if(j==-1||s[i]==t[j]){ ++i; ++j; } else j=_next[j]; } if(j>=lent)return i-lent; else return -1; } int KMPCount(char s[],char t[]){//统计子串在主串中的出现次数,可重叠 int i,j,lens,lent,cnt; i=j=0; lens=strlen(s); lent=strlen(t); cnt=0; while(i<lens){ if(j==-1||s[i]==t[j]){ ++i; ++j; } else j=_next[j]; if(j==lent)++cnt; } return cnt; } void KMPCount2(char t[]){//统计单串中从某个位置以前有多少重复的串 int i,lent,tmp; lent=strlen(t); for(i=2;i<=lent;++i){ tmp=i-_next[i];//tmp是0...i-1这一串的最小循环节长度 if(i%tmp==0&&i/tmp>1) printf(" 位置:%d 个数:%d ",i,i/tmp); } } int main(){ char str1[MAXN],str2[MAXN]; int i,len2; printf("输入主串、子串:"); while(~scanf("%s%s",str1,str2)){ GetNext(str2);//求子串的next数组 //输出next数组的值 printf("next:"); len2=strlen(str2); for(i=0;i<=len2;++i) printf("%d ",_next[i]); printf(" "); printf("首次出现位置:%d ",KMPIndex(str1,str2)); printf("子串在主串中的出现次数:%d ",KMPCount(str1,str2)); printf("子串中的重复串: "); KMPCount2(str2); printf("输入主串、子串:"); } return 0; }
2.扩展kmp
/* 扩展kmp */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; #define MaxSize 1024 int _next[MaxSize],extend[MaxSize]; //扩展kmp //next[i]:x[i...m-1]与x[0...m-1]的最长公公前缀 //extend[i]:y[i...n-1]与x[0...m-1]的最长公共前缀 void pre_EKMP(char x[],int m,int _next[]){//m长度 _next[0]=m; int j=0; while(j+1<m&&x[j]==x[j+1])j++; _next[1]=j; int k=1; for(int i=2;i<m;i++){ int p=_next[k]+k-1; int L=_next[i-k]; if(i+L<p+1)_next[i]=L; else{ j=max(0,p-i+1); while(i+j<m&&x[i+j]==x[j])j++; _next[i]=j; k=i; } } } void EKMP(char x[],int m,char y[],int n,int _next[],int extend[]){//x子串,m子串长度,y主串,n主串长度 pre_EKMP(x,m,_next); int j=0; while(j<n&&j<m&&x[j]==y[j])j++; extend[0]=j; int k=0; for(int i=1;i<n;i++){ int p=extend[k]+k-1; int L=_next[i-k]; if(i+L<p+1)extend[i]=L; else{ j=max(0,p-i+1); while(i+j<n&&j<m&&y[i+j]==x[j])j++; extend[i]=j; k=i; } } } /* 子串 :a b a b 主串 :a b a b a c next :4 0 2 0 extend:4 0 3 0 1 0 */ int main(){ char str1[32],str2[32];//子串,主串 int i,len1,len2;//子串长度,主串长度 scanf("%s%s",str1,str2); len1=strlen(str1); len2=strlen(str2); EKMP(str1,len1,str2,len2,_next,extend); for(i=0;i<len1;++i) printf("%d ",_next[i]); printf(" "); for(i=0;i<len2;++i) printf("%d ",extend[i]); printf(" "); return 0; }
3.Manacher
/* Manacher */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; //求最长回文子串 const int MAXN=110010; char Ma[MAXN*2]; int Mp[MAXN*2]; void Manacher(char s[],int len){ int l=0; Ma[l++]='$'; Ma[l++]='#'; for(int i=0;i<len;i++){ Ma[l++]=s[i]; Ma[l++]='#'; } Ma[l]=0; int mx=0,id=0; for(int i=0;i<l;i++){ Mp[i]=mx>i?min(Mp[2*id-i],mx-i):1; while(Ma[i+Mp[i]]==Ma[i-Mp[i]])Mp[i]++; if(i+Mp[i]>mx){ mx=i+Mp[i]; id=i; } } } /* abaaba i: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 Ma[i]:$ # a # b # a # a # b # a # Mp[i]:1 1 2 1 4 1 2 7 2 1 4 1 2 1 */ char s[MAXN]; int main(){ while(scanf("%s",s)==1){ int len=strlen(s); Manacher(s,len); int ans=0; for(int i=0;i<2*len+2;i++) ans=max(ans,Mp[i]-1); printf("%d ",ans); } return 0; }
4.ac自动机
/* ac自动机模板 n个关键字,1段描述,求描述中出现了多少关键字 */ #include<iostream> #include<stdio.h> #include<string.h> #include<queue> using namespace std; struct Trie{ int next[500010][26],fail[500010],end[500010]; int root,L; int newnode(){ for(int i=0;i<26;i++) next[L][i]=-1; end[L++]=0; return L-1; } void init(){ L=0; root=newnode(); } void insert(char buf[]){ int len=strlen(buf); int now=root; for(int i=0;i<len;i++){ if(next[now][buf[i]-'a']==-1) next[now][buf[i]-'a']=newnode(); now=next[now][buf[i]-'a']; } end[now]++; } void build(){ queue<int>Q; fail[root]=root; for(int i=0;i<26;i++) if(next[root][i]==-1) next[root][i]=root; else{ fail[next[root][i]]=root; Q.push(next[root][i]); } while(!Q.empty()){ int now=Q.front(); Q.pop(); for(int i=0;i<26;i++) if(next[now][i]==-1) next[now][i]=next[fail[now]][i]; else{ fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } int query(char buf[]){ int len=strlen(buf); int now=root; int res=0; for(int i=0;i<len;i++){ now=next[now][buf[i]-'a']; int temp=now; while(temp!=root){ res+=end[temp]; end[temp]=0; temp=fail[temp]; } } return res; } void debug(){ for(int i=0;i<L;i++){ printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]); for(int j=0;j<26;j++) printf("%2d",next[i][j]); printf("] "); } } }; char buf[1000010]; Trie ac; int main(){ int T; int n; scanf("%d",&T); while(T--){ scanf("%d",&n); ac.init(); for(int i=0;i<n;i++){ scanf("%s",buf); ac.insert(buf); } ac.build(); scanf("%s",buf); printf("%d ",ac.query(buf)); } return 0; }
5.trie树(字典树)
c.动态开辟:
/* trie树(字典树) 动态开辟 */ #include<iostream> #include<string.h> using namespace std; const int MAX=26; struct Trie { Trie *next[MAX]; int v; //根据需要变化,1代表无此单词,-1代表有此单词 }; Trie *root=new Trie; void createTrie(char *str) { int len = strlen(str); Trie *p = root, *q; for(int i=0; i<len; ++i) { int id = str[i]-'a'; if(p->next[id] == NULL) { // q = (Trie *)malloc(sizeof(Trie)); q = new Trie; q->v = 1; //初始v==1 for(int j=0; j<MAX; ++j) q->next[j] = NULL; p->next[id] = q; } p = p->next[id]; } p->v = -1; //若为结尾,则将v改成-1表示 } int findTrie(char *str) { int len = strlen(str); Trie *p = root; for(int i=0; i<len; ++i) { int id = str[i]-'a'; p = p->next[id]; if(p == NULL) //若为空集,表示不存以此为前缀的串 return 0; if(p->v == -1) //字符集中已有串是此串的前缀 return 1; } return 2; //此串是字符集中某串的前缀 } int deleteTrie(Trie* T) { int i; if(T==NULL) return 0; for(i=0; i<MAX; i++) { if(T->next[i]!=NULL) deleteTrie(T->next[i]); } //free(T); delete(T); return 0; } int main() { char str[20]; int i; for(i=0; i<MAX; i++) root->next[i]=NULL; cout<<"输入串1:"; cin>>str; createTrie(str); cout<<"输入串2:"; cin>>str; cout<<findTrie(str)<<endl; return 0; }
c2.静态数组:抽空补上。
6.后缀数组
c.DA
/* 后缀数组 DA */ #include<iostream> #include<stdio.h> #include<string.h> using namespace std; const int MAXN=20010; int t1[MAXN],t2[MAXN],c[MAXN]; bool cmp(int *r,int a,int b,int l){ return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int str[],int sa[],int rank[],int height[],int n,int m){ n++; int i,j,p,*x=t1,*y=t2; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[i]=str[i]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; for(j=1;j<=n;j<<=1){ p=0; for(i=n-j;i<n;i++)y[p++]=i; for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; for(i=0;i<m;i++)c[i]=0; for(i=0;i<n;i++)c[x[y[i]]]++; for(i=1;i<m;i++)c[i]+=c[i-1]; for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; swap(x,y); p=1;x[sa[0]]=0; for(i=1;i<n;i++) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; if(p>=n)break; m=p; } int k=0; n--; for(i=0;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;i++){ if(k)k--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } } int rank[MAXN],height[MAXN]; int RMQ[MAXN]; int mm[MAXN]; int best[20][MAXN]; void initRMQ(int n){ mm[0]=-1; for(int i=1;i<=n;i++) mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1]; for(int i=1;i<=n;i++)best[0][i]=i; for(int i=1;i<=mm[n];i++) for(int j=1;j+(1<<i)-1<=n;j++){ int a=best[i-1][j]; int b=best[i-1][j+(1<<(i-1))]; if(RMQ[a]<RMQ[b])best[i][j]=a; else best[i][j]=b; } } int askRMQ(int a,int b){ int t; t=mm[b-a+1]; b-=(1<<t)-1; a=best[t][a];b=best[t][b]; return RMQ[a]<RMQ[b]?a:b; } int lcp(int a,int b){ a=rank[a];b=rank[b]; if(a>b)swap(a,b); return height[askRMQ(a+1,b)]; } char str[MAXN]; int r[MAXN]; int sa[MAXN]; int main(){ while(scanf("%s",str)==1){ int len=strlen(str); int n=2*len+1; for(int i=0;i<len;i++)r[i]=str[i]; for(int i=0;i<len;i++)r[len+1+i]=str[len-1-i]; r[len]=1; r[n]=0; da(r,sa,rank,height,n,128); for(int i=1;i<=n;i++)RMQ[i]=height[i]; initRMQ(n); int ans=0,st; int tmp; for(int i=0;i<len;i++){ tmp=lcp(i,n-i); if(2*tmp>ans){ ans=2*tmp; st=i-tmp; } tmp=lcp(i,n-i-1); if(2*tmp>ans){ ans=2*tmp-1; st=i-tmp+1; } } str[st+ans]=0; printf("%s ",str+st); } return 0; }
c2.DC3
/* 后缀数组 DC3 */ #include<iostream> #include<stdio.h> using namespace std; const int MAXN=2010; #define F(x) ((x)/3+((x)%3==1?0:tb)) #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2) int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3]; int c0(int *r,int a,int b){ return r[a]==r[b]&&r[a+1]==r[b+1]&&r[a+2]==r[b+2]; } int c12(int k,int *r,int a,int b){ if(k==2) return r[a]<r[b]||(r[a]==r[b]&&c12(1,r,a+1,b+1)); else return r[a]<r[b]||(r[a]==r[b]&&wv[a+1]<wv[b+1]); } void sort(int *r,int *a,int *b,int n,int m){ int i; for(i=0;i<n;i++)wv[i]=r[a[i]]; for(i=0;i<m;i++)wss[i]=0; for(i=0;i<n;i++)wss[wv[i]]++; for(i=1;i<m;i++)wss[i]+=wss[i-1]; for(i=n-1;i>=0;i--) b[--wss[wv[i]]]=a[i]; } void dc3(int *r,int *sa,int n,int m){ int i,j,*rn=r+n; int *san=sa+n,ta=0,tb=(n+1)/3,tbc=0,p; r[n]=r[n+1]=0; for(i=0;i<n;i++)if(i%3!=0)wa[tbc++]=i; sort(r+2,wa,wb,tbc,m); sort(r+1,wb,wa,tbc,m); sort(r,wa,wb,tbc,m); for(p=1,rn[F(wb[0])]=0,i=1;i<tbc;i++) rn[F(wb[i])]=c0(r,wb[i-1],wb[i])?p-1:p++; if(p<tbc)dc3(rn,san,tbc,p); else for(i=0;i<tbc;i++)san[rn[i]]=i; for(i=0;i<tbc;i++)if(san[i]<tb)wb[ta++]=san[i]*3; if(n%3==1)wb[ta++]=n-1; sort(r,wb,wa,ta,m); for(i=0;i<tbc;i++)wv[wb[i]=G(san[i])]=i; for(i=0,j=0,p=0;i<ta&&j<tbc;p++) sa[p]=c12(wb[j]%3,r,wa[i],wb[j])?wa[i++]:wb[j++]; for(;i<ta;p++)sa[p]=wa[i++]; for(;j<tbc;p++)sa[p]=wb[j++]; } void da(int str[],int sa[],int rank[],int height[],int n,int m){ for(int i=n;i<n*3;i++) str[i]=0; dc3(str,sa,n+1,m); int i,j,k=0; for(i=0;i<=n;i++)rank[sa[i]]=i; for(i=0;i<n;i++){ if(k)k--; j=sa[rank[i]-1]; while(str[i+k]==str[j+k])k++; height[rank[i]]=k; } } int main(){ return 0; }