题意
给出一个字符串,求它的最小表示法。
分析
这个题当然可以用最小表示法做啦!但是我是为了学后缀自动机鸭!
我们把这个字符串长度乘二,然后建SAM,然后在SAM上每次跑最小的那个字母,找出长度为n的时候就停下。如果停下的那个状态时u,那么ans=st[u].len-n+1
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <map> 6 7 using namespace std; 8 const int maxn=20000+100; 9 char s[maxn]; 10 int n,T; 11 struct state{ 12 map<char,int>next; 13 int len,link; 14 }st[4*maxn]; 15 int last,cnt,cur; 16 void init(){ 17 last=cur=0; 18 cnt=1; 19 st[0].len=0; 20 st[0].link=-1; 21 st[0].next.clear(); 22 } 23 void build(char c){ 24 cur=cnt++; 25 st[cur].next.clear(); 26 st[cur].len=st[last].len+1; 27 int p; 28 for(p=last;p!=-1&&!st[p].next.count(c);p=st[p].link) 29 st[p].next[c]=cur; 30 if(p==-1) 31 st[cur].link=0; 32 else{ 33 int q=st[p].next[c]; 34 if(st[p].len+1==st[q].len) 35 st[cur].link=q; 36 else{ 37 int clone=cnt++; 38 st[clone].next=st[q].next; 39 st[clone].link=st[q].link; 40 st[clone].len=st[p].len+1; 41 for(;p!=-1&&st [p].next[c]==q;p=st[p].link) 42 st[p].next[c]=clone; 43 st[q].link=clone;st[cur].link=clone; 44 } 45 } 46 last=cur; 47 } 48 int main(){ 49 scanf("%d",&T); 50 for(int t=1;t<=T;t++){ 51 scanf("%s",s); 52 n=strlen(s); 53 for(int i=0;i<n;i++) 54 s[i+n]=s[i]; 55 init(); 56 for(int i=0;i<n;i++) 57 build(s[i]); 58 for(int i=n;i<2*n;i++) 59 build(s[i]); 60 int u=0; 61 for(int i=0;i<n;i++){ 62 for(int j=‘a‘;j<=‘z‘;j++){ 63 if(st[u].next.count(j)){ 64 u=st[u].next[j]; 65 break; 66 } 67 } 68 } 69 int ans=st[u].len-n+1; 70 printf("%d\n",ans); 71 } 72 return 0; 73 }
原文地址:https://www.cnblogs.com/LQLlulu/p/9882133.html
时间: 2024-10-11 12:47:37