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

题面就不弄了

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

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

倒序添加到原串上即可。

也就是我们可以固定一个位置,即使反串的第一个单词(原串最后一个),然后从该位置向前向后遍历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 }

原文地址:https://www.cnblogs.com/iwannabe/p/11483276.html

时间: 2025-01-10 03:06:40

Extend to Palindrome UVA - 11475 (后缀数组)的相关文章

UVA 11475 后缀数组/KMP

题目链接: 题意:给定一个只含字母的字符串,求在字符串末尾添加尽量少的字符使得字符串为回文串. 思路:因为只能从末尾添加字符,所以其实求的是最长的后缀回文串.那么添加的字符为除了这个原串的最长后缀回文串之外的其他字符.于是问题就转变成了求字符串的最长后缀回文串,对于后缀数组求回文串子串的做法,将整个字符串反过来写在原字符串后面,中间用一个特殊的字符隔开.这样就把问题变为了求这个新的字符串的某两个后缀的最长公共前缀.奇数长度和偶数长度的分开做.对于求奇数长度,假设现在枚举的位置为i,那么对应在反过

UVA 11475 Extend to Palindrome(后缀数组+ST表)

[题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串. [题解] 用拼接符将原字符串倒序相接,做一遍后缀数组,查询两串相应位置的LCP就是以该点为中心的回文串长度的一半分,奇偶求出所有后缀回文串,保留最长的,则补充部分为剩下的前缀的倒置.至于查询两串的LCP我们可以在height数组建立ST表查询. [代码] #include <cstdio> #

uva 10829 - L-Gap Substrings(后缀数组)

题目链接:uva 10829 - L-Gap Substrings 题目大意:给定一个字符串,问有多少字符串满足UVU的形式,要求U非空,V的长度为g. 解题思路:对字符串的正序和逆序构建后缀数组,然后枚举U的长度l,每次以长度l分区间,在l和l+d+g所在的两个区间上确定U的最大长度. #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> using nam

uva 10526 - Intellectual Property(后缀数组)

题目链接:uva 10526 - Intellectual Property 题目大意:给定两个文本,问说下面一个文本中在哪些位置上抄袭了上面个一个文本的,输出n个抄袭位置(不足n个情况全部输出),按照长度优先输出,长度相同的输出位置靠前的. 注意:空格,回车都算一个字符:一段字符只能是抄袭上面的一部分,比如上:NSB*SB 下:NSB 答案:NSB. 解题思路:将两个文本连接在一起,中间用没有出现的字符分割,然后处理处后缀数组,根据height数组的性质,求出哪些位置匹配的长度不为0(注意匹配

uva 11855 - Buzzwords(后缀数组)

题目链接:uva 11855 - Buzzwords 题目大意:给定一个字符串,输出重复子串长度大于1的重复次数(每种长度只算一个次数最多的),并且按照从大到小输出. 解题思路:后缀数组,处理处后缀数组,然后枚举子串长度,按照长度分段即可. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int max

【后缀数组|最长回文子串】URAL-1297 Palindrome

1297.Palindrome Time limit: 1.0 second Memory limit: 64 MB The "U.S. Robots" HQ has just received a rather alarming anonymous letter. It states that the agent from the competing ?Robots Unlimited? has infiltrated into "U.S. Robotics".

uva 261 - The Window Property(后缀数组)

题目链接:uva 261 - The Window Property 题目大意:给定给一个字符串,枚举子串长度k(len≥k≥1),要求在任意k时,有不超过k+1个不同的子串,如果有的话则输出NO,并且输出最早发现不满足的位置. 解题思路:后缀数组,处理出height数组,对于每个k,遍历height数组,碰到小于k的则分段,将整个height分成若干段,即为有多少种长度为k的不同前缀,需要注意的是要跳过前缀长度不足k的. #include <cstdio> #include <cstr

uva 12338 - Anti-Rhyme Pairs(后缀数组+RMQ)

题目链接:uva 12338 - Anti-Rhyme Pairs 题目大意:给定若干个字符串,每次询问两个字符串的最长公共前缀. 解题思路:本来应该将每个字符串连接起来做后缀数组,但其实可以直接把一个字符串看成是一个字符,然后排序了就对应是SA数组,然后处理height即可.然后根据后缀数组的性质,字符串i和j的最长公共前缀长度即为rank[i]+1~rank[j]之间height的最小值.特判i=j的情况. #include <cstdio> #include <cstring>

uva 11107 - Life Forms(后缀数组)

题目链接:uva 11107 - Life Forms 题目大意:给定n个字符串,求一个最长的字符串,为n/2个字符串的子串. 解题思路:后缀数组,处理除后缀数组后,二分长度,每次遍历height数组,当长度不足时就分段,如果存在一段中包含n/2个起点,则为可行长度. #include <cstdio> #include <cstring> #include <set> #include <algorithm> using namespace std; co