题面就不弄了
题意:给你一个串,让你求出补充最少的字符形成的回文串
思路:思路很好想,就是对一个串,找其最后一个字符(第一个也行)和原串的反串的最长公共前缀,这样就求出了该串中的已有最长回文,然后把剩下部分
倒序添加到原串上即可。
也就是我们可以固定一个位置,即使反串的第一个单词(原串最后一个),然后从该位置向前向后遍历ht数组直到找到一个属于原串即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 8 const int maxn = 2e5+10; 9 string s; 10 int sa[maxn],t[maxn],t2[maxn],c[maxn]; 11 12 void build_sa(int n,int m) 13 { 14 int i,*x=t,*y=t2; 15 for(i=0; i<m; i++)c[i]=0; 16 for(i=0; i<n; i++)c[x[i]=s[i]]++; 17 for(i=1; i<m; i++)c[i]+=c[i-1]; 18 for(i=n-1; i>=0; i--)sa[--c[x[i]]]=i; 19 for(int k=1; k<=n; k<<=1) 20 { 21 int p=0; 22 for(i=n-k; i<n; i++)y[p++]=i; 23 for(i=0; i<n; i++)if(sa[i] >= k)y[p++]=sa[i]-k; 24 for(i=0; i<m; i++)c[i] = 0; 25 for(i=0; i<n; i++)c[x[y[i]]]++; 26 for(i=1; i<m; i++)c[i]+=c[i-1]; 27 for(i=n-1; i>=0; i--)sa[--c[x[y[i]]]] = y[i]; 28 swap(x,y); 29 p=1,x[sa[0]]=0; 30 for(i=1; i<n; i++) 31 x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k]?p-1:p++; 32 if(p>=n)break; 33 m=p; 34 } 35 } 36 37 int ht[maxn],rk[maxn]; 38 39 void getHeight(int n) 40 { 41 int i,j,k=0; 42 for(i=0; i<n; i++)rk[sa[i]] = i; 43 for(i=0; i<n-1; i++) 44 { 45 if(k)k--; 46 if(s[i] == '$')continue; 47 int j = sa[rk[i]-1]; 48 while(s[i+k] == s[j+k] && s[i+k] != '$')k++; 49 ht[rk[i]] = k; 50 } 51 } 52 53 char tmp[maxn]; 54 int len[3]; 55 int main() 56 { 57 while(~scanf("%s",tmp)) 58 { 59 int tmp_len = strlen(tmp); 60 s.clear(); 61 s+=tmp; 62 s+='$'; 63 len[1] = s.length(); 64 reverse(tmp,tmp+tmp_len); 65 s+=tmp; 66 s+='$'; 67 len[2] = s.length(); 68 build_sa(len[2],130); 69 getHeight(len[2]); 70 71 // for(int i=2;i<len[2];i++)printf("%d %d===\n",sa[i],ht[i]); 72 int maxx = 0; 73 int pos = rk[len[1]]; 74 int now = pos; 75 int minn = 0x3f3f3f3f; 76 while(now > 1 && ht[now] > maxx ) 77 { 78 minn = min(minn,ht[now]); 79 if(sa[now-1]+1 < len[1] && sa[now-1] + minn == len[1] - 1){maxx = minn;break;} 80 now--; 81 } 82 now = pos+1; 83 minn = 0x3f3f3f3f; 84 while(now < len[2]&&ht[now] > maxx) 85 { 86 minn = min(minn,ht[now]); 87 if(sa[now] + 1 < len[1] && sa[now]+minn == len[1] - 1){maxx = minn;break;} 88 now++; 89 } 90 for(int i=tmp_len-1;i>=0;i--)printf("%c",tmp[i]); 91 for(int i=maxx;i<tmp_len;i++)printf("%c",tmp[i]); 92 puts(""); 93 } 94 }View Code