题目链接:点击打开链接

题意:给你一个串,让你在串后面添加尽可能少的字符使得这个串变成回文串。

思路:这题可以kmp,manacher,后缀数组三种方法都可以做,kmp和manacher效率较高,时间复杂度是O(n),后缀数组时间复杂度是O(nlogn).思路是求出元串的后缀和反串的前缀匹配的最大长度。用后缀数组的时候求出l=lcp(i,len+1),判断l+i是不是等于len,如果等于那么就是结果。

kmp:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 1000600
char s1[maxn],s2[maxn];
int nextt[maxn],len;
int pd(char *s1,char *s2){
int i,j,len1,len2;
len1=len2=len;
i=0;j=-1;
memset(nextt,-1,sizeof(nextt));
while(i<len2){
if(j==-1 || s2[i]==s2[j]){
i++;
j++;
nextt[i]=j;
}
else j=nextt[j];
}
i=0;j=0;
int ans=1;
while(i<len1 && j<len2){
if(j==-1 || s1[i]==s2[j]){
//ans=max(ans,j+1); 注意这句不能加,因为要求的是当i=len1时候,串二最大匹配了多少长度
i++;
j++;
}
else j=nextt[j]; //这里要解释一下,这里的意思是s[i]和s[j]不匹配了,那么看前j个字符前缀和后缀匹配的程度,注意,这里前j个字符是s[0]...s[j-1]
}
ans=j;
return ans;
} int main()
{
int n,m,i,j,ans;
while(scanf("%s",s1)!=EOF)
{
strcpy(s2,s1);
len=strlen(s1);
reverse(s2,s2+len);
ans=pd(s1,s2);
printf("%s",s1);
for(i=len-1-ans;i>=0;i--){
printf("%c",s1[i]);
}
printf("\n");
}
return 0;
}

manacher:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define maxn 100060
char s[maxn],ss[maxn*2]; //要开两倍大小
int p[maxn*2];
int main()
{
int n,m,i,j,mx,idx,maxx,len,len1;
while(scanf("%s",s)!=EOF)
{
len=strlen(s);
len1=len;
ss[0]='$';
ss[1]='#';
for(i=0;i<len;i++){
ss[i*2+2]=s[i];
ss[i*2+3]='#';
}
mx=0;maxx=0;
len=2*len+2;
int ans=inf;
for(i=1;i<len;i++){
if(mx>i){ //这里的mx为满足条件的后一个,这样如果i<=idx+p[i]-1就能比较了
p[i]=min(p[idx*2-i],mx-i);
}
else p[i]=1;
while(ss[i+p[i]]==ss[i-p[i]]){
p[i]++;
}
if(maxx<p[i])maxx=p[i];
if(mx<i+p[i]){ //这里更新的mx也是范围内的后一个
mx=i+p[i];
idx=i;
}
if(i+p[i]-1==len-1 ){
//printf("--->%d\n",i);
ans=min(ans,(i-(p[i]-1)) /2 );
}
}
printf("%s",s);
for(i=ans-1;i>=0;i--){
printf("%c",s[i]);
}
printf("\n"); //printf("%d\n",ans);
}
return 0;
}

后缀数组:

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<bitset>
#include<algorithm>
using namespace std;
#define lson th<<1
#define rson th<<1|1
typedef long long ll;
typedef long double ldb;
#define inf 99999999
#define pi acos(-1.0)
#define M 100050
#define maxn 200050
char s1[M],s2[M];
int a[maxn];
int idx(char c){
if(c>='a' && c<='z')return c-'a'+1;
if(c>='A' && c<='Z')return c-'A'+1+26;
} int sa[maxn];
int wa[maxn],wb[maxn],wv[maxn],we[maxn];
int rk[maxn],height[maxn];
int cmp(int *r,int a,int b,int l){
return r[a]==r[b]&&r[a+l]==r[b+l];
}
void build_sa(int *r,int n,int m)
{
int i,j,p,*x=wa,*y=wb,*t;
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[x[i]=r[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[x[i]]]=i;
for(j=1,p=1;p<n;j*=2,m=p){
for(p=0,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<n;i++)wv[i]=x[y[i]];
for(i=0;i<m;i++)we[i]=0;
for(i=0;i<n;i++)we[wv[i]]++;
for(i=1;i<m;i++)we[i]+=we[i-1];
for(i=n-1;i>=0;i--)sa[--we[wv[i]]]=y[i];
for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
}
} void calheight(int *r,int n)
{
int i,j,k=0;
for(i=1;i<=n;i++)rk[sa[i]]=i;
for(i=0;i<n;height[rk[i++] ]=k){
for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
}
} int minx[200100][30];
void init_rmq(int n)
{
int i,j;
for(i=1;i<=n;i++)minx[i][0]=height[i];
for(j=1;j<=20;j++){
for(i=1;i<=n;i++){
if(i+(1<<j)-1<=n)
{
minx[i][j]=min(minx[i][j-1],minx[i+(1<<(j-1))][j-1]);
}
}
}
} int lcp(int l,int r)
{
int k,i;
l=rk[l];r=rk[r];
if(l>r)swap(l,r);
l++;
k=(log((r-l+1)*1.0)/log(2.0));
return min(minx[l][k],minx[r-(1<<k)+1][k]);
} int main()
{
int n,m,i,j,len,l;
while(scanf("%s",s1)!=EOF)
{
strcpy(s2,s1);
len=strlen(s1);
reverse(s2,s2+len);
n=0;
for(i=0;i<len;i++){
a[n++]=idx(s1[i]);
}
a[n++]=55;
for(i=0;i<len;i++){
a[n++]=idx(s2[i]);
}
a[n]=0; build_sa(a,n+1,60);
calheight(a,n);
init_rmq(n); for(i=0;i<len;i++){
l=lcp(i,len+1);
if(i+l==len)break;
}
printf("%s",s1);
for(i=len-1-l;i>=0;i--){
printf("%c",s1[i]);
}
printf("\n");
}
return 0;
}

UVA 11475 Extend to Palindrome (kmp || manacher || 后缀数组)的更多相关文章

  1. uva 11475 - Extend to Palindrome(KMP)

    option=com_onlinejudge&Itemid=8&category=506&page=show_problem&problem=2470" ta ...

  2. UVA - 11475 Extend to Palindrome —— 字符串哈希 or KMP or 后缀数组

    题目链接:https://vjudge.net/problem/UVA-11475 题意: 给出一个字符串,问在该字符串后面至少添加几个字符,使得其成为回文串,并输出该回文串. 题解: 实际上是求该字 ...

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

    Your task is, given an integer N, to make a palidrome (word that reads the same when you reverse it) ...

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

    [题目链接] http://acm.hust.edu.cn/vjudge/problem/27647 [题目大意] 给出一个字符串,要求在其后面添加最少的字符数,使得其成为一个回文串.并输出这个回文串 ...

  5. UVA 11475 Extend to Palindrome(hash)题解

    题意:问你最少加几个字母使所给串变成回文串. 思路:一开始打算将正序和逆序都hash,然后用提取前缀后缀的方法来找,但是RE了,debug失败遂弃之.后来发现可以直接hash,一边hash一边比较.我 ...

  6. UVa 11475 - Extend to Palindrome

    題目:給你一個字符串,在後面拼接一部分使得它變成回文串,使得串最短.輸出這個回文串. 分析:KMP,dp.這裡利用KMP算法將串和它的轉置匹配,看結束時匹配的長度就可以. 因為串比较長.使用KMP比较 ...

  7. UVA 11475 Extend to Palindrome hash

    题意: 给出一个字符串,让你往后添加最少的字符,使其成为回文串. 分析: 题目就相当于求后缀字符串为回文串的最长长度,判断回文串要O(n)时间,直接判断肯定不行.我们从后往前枚举,每次字符串与上一个字 ...

  8. HDU 3948 The Number of Palindromes(Manacher+后缀数组)

    题意 求一个字符串中本质不同的回文子串的个数. $ 1\leq |string| \leq 100000$ 思路 好像是回文自动机的裸题,但是可以用 \(\text{Manacher}\) (马拉车) ...

  9. [APIO2014]回文串 manacher 后缀数组

    题面:洛谷 题解: 还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个. 所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa. 然后对于每个回文串,求出它的出现次数,更新 ...

随机推荐

  1. 【MyBatis】MyBatis 动态 SQL

    MyBatis 动态SQL if 可以根据实体类的不同取值,使用不同的 SQL 语句来进行查询. 使用动态 SQL 最常见情景是根据条件包含 where 子句的一部分. 持久层 DAO 接口: pub ...

  2. 美业黑科技 ▏肌肤管家SkinRun V3S智能肌肤测试仪,实现“护肤”私人定制

    肌肤如同身体,也需要定时的"健康检查",但仅凭肉眼难以窥见深层的肌肤问题.而现在,肌肤管家SkinRun前沿黑科技护肤测试仪--SkinRun V3S便能帮助用户对症下药.肌肤管家 ...

  3. Java虚拟机常用的性能监控工具

    基础故障处理工具 jps: 虚拟机进程状况工具 功能:来处正在运行的虚拟机进程,并显示虚拟机执行主类名称,以及本地虚拟机唯一ID. 它是使用频率最高的命令行工具,因为其他JDK工具大多需要输入他查询到 ...

  4. Sentry(v20.12.1) K8S 云原生架构探索,SENTRY FOR JAVASCRIPT 故障排除

    系列 Sentry-Go SDK 中文实践指南 一起来刷 Sentry For Go 官方文档之 Enriching Events Snuba:Sentry 新的搜索基础设施(基于 ClickHous ...

  5. 【Java】运算符(算术、赋值、比较(关系)、逻辑、条件、位运算符)

    运算符 文章目录 运算符 1. 算术运算符 2. 赋值运算符 3. 比较运算符 4. 逻辑运算符 5. 条件运算符 6. 位运算符 7. 运算符优先级 8. 运算符操作数类型说明 9.code 算术运 ...

  6. 【Spring】Spring的数据库开发 - 2、Spring JdbcTemplate的常用方法(execute、update、query)

    Spring JdbcTemplate的常用方法 文章目录 Spring JdbcTemplate的常用方法 execute() update() query() 简单记录-Java EE企业级应用开 ...

  7. 【windows】快捷键

    Ctrl+字母键 1.Ctrl+A:全选 2.Ctrl+C:复制选择的项目 3.Ctrl+E:选择搜索框 4.Ctrl+F:选择搜索框 5.Ctrl+N:创建新的项目 6.Ctrl+W:关闭当前窗口 ...

  8. SDUST数据结构 - chap7 图

    判断题: 选择题: 函数题: 6-1 邻接矩阵存储图的深度优先遍历: 裁判测试程序样例: #include <stdio.h> typedef enum {false, true} boo ...

  9. ctfhub技能树—sql注入—报错注入

    打开靶机 payload 1 Union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.c ...

  10. InnoDB的主键选择与插入优化

    索引的存放方式MyISAM和InnoDB存储引擎在MySQL中,不同存储引擎对索引的实现方式是不同的,总结下MyISAM和InnoDB两个存储引擎的索引实现方式.MyISAM引擎使用B+Tree作为索 ...