Extend to Palindrome UVA - 11475 (后缀数组)

题面就不弄了

 

题意:给你一个串,让你求出补充最少的字符形成的回文串

思路:思路很好想,就是对一个串,找其最后一个字符(第一个也行)和原串的反串的最长公共前缀,这样就求出了该串中的已有最长回文,然后把剩下部分

倒序添加到原串上即可。

也就是我们可以固定一个位置,即使反串的第一个单词(原串最后一个),然后从该位置向前向后遍历ht数组直到找到一个属于原串即可。

Extend to Palindrome UVA - 11475 (后缀数组)
 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

 

上一篇:UVA401 回文词(字符串二维数组,ctype.h全家桶)


下一篇:LeetCode 9. Palindrome Number