• [kuangbin专题] Manacher


    https://vjudge.net/contest/284138#overview

    A、Palindrome

    最长回文子串,Manacher模板题

     1 #include<iostream>
     2 #include<sstream>
     3 #include<fstream>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<iomanip>
     7 #include<cstdlib>
     8 #include<cctype>
     9 #include<vector>
    10 #include<string>
    11 #include<cmath>
    12 #include<ctime>
    13 #include<stack>
    14 #include<queue>
    15 #include<map>
    16 #include<set>
    17 #define mem(a,b) memset(a,b,sizeof(a))
    18 #define random(a,b) (rand()%(b-a+1)+a)
    19 #define ll long long
    20 #define ull unsigned long long
    21 #define e 2.71828182
    22 #define Pi acos(-1.0)
    23 #define ls(rt) (rt<<1)
    24 #define rs(rt) (rt<<1|1)
    25 #define lowbit(x) (x&(-x))
    26 using namespace std;
    27 const int MAXN=1e6+5;
    28 char str[MAXN],nstr[MAXN<<1];
    29 int r[MAXN<<1];
    30 int len;
    31 int read()
    32 {
    33     int s=1,x=0;
    34     char ch=getchar();
    35     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
    36     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
    37     return x*s;
    38 }
    39 int Manacher()
    40 {
    41     for(int i=1;i<=len;++i) nstr[2*i-1]='%',nstr[2*i]=str[i];
    42     nstr[len=2*len+1]='%';
    43     int pos=0,R=0;
    44     for(int i=1;i<=len;++i)
    45     {
    46         if(i<R) r[i]=min(r[2*pos-i],R-i);
    47         else r[i]=1;
    48         while(i-r[i]>=1&&i+r[i]<=len&&nstr[i-r[i]]==nstr[i+r[i]]) r[i]++;
    49         if(i+r[i]>R) pos=i,R=i+r[i];
    50     }
    51     int res=0;
    52     for(int i=1;i<=len;++i) res=max(res,r[i]-1);
    53     return res;
    54 }
    55 int main()
    56 {
    57     ios::sync_with_stdio(false);
    58     cin.tie(0);cout.tie(0);
    59     int cnt=0;
    60     while(true)
    61     {
    62         cin>>str+1;
    63         len=strlen(str+1);
    64         if(str[1]=='E') return 0;
    65         cout<<"Case "<<++cnt<<": "<<Manacher()<<endl;
    66     }
    67 }
    View Code

    B、吉哥系列故事——完美队形II

    最长非递减回文子串,在Manacher基础上修改,增加nstr[i-r[i]]<=nstr[i-r[i]+2]

     1 #include<iostream>
     2 #include<sstream>
     3 #include<fstream>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<iomanip>
     7 #include<cstdlib>
     8 #include<cctype>
     9 #include<vector>
    10 #include<string>
    11 #include<cmath>
    12 #include<ctime>
    13 #include<stack>
    14 #include<queue>
    15 #include<map>
    16 #include<set>
    17 #define mem(a,b) memset(a,b,sizeof(a))
    18 #define random(a,b) (rand()%(b-a+1)+a)
    19 #define ll long long
    20 #define ull unsigned long long
    21 #define e 2.71828182
    22 #define Pi acos(-1.0)
    23 #define ls(rt) (rt<<1)
    24 #define rs(rt) (rt<<1|1)
    25 #define lowbit(x) (x&(-x))
    26 using namespace std;
    27 const int MAXN=1e6+5;
    28 int str[MAXN],nstr[MAXN<<1];
    29 int r[MAXN<<1];
    30 int len;
    31 int read()
    32 {
    33     int s=1,x=0;
    34     char ch=getchar();
    35     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
    36     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
    37     return x*s;
    38 }
    39 int Manacher()
    40 {
    41     for(int i=1;i<=len;++i) nstr[2*i-1]=251,nstr[2*i]=str[i];
    42     nstr[len=2*len+1]=251;
    43     int pos=0,R=0;
    44     for(int i=1;i<=len;++i)
    45     {
    46         if(i<R) r[i]=min(r[2*pos-i],R-i);
    47         else r[i]=1;
    48         while(i-r[i]>=1&&i+r[i]<=len&&nstr[i-r[i]]==nstr[i+r[i]]
    49              &&nstr[i-r[i]]<=nstr[i-r[i]+2]) r[i]++;
    50         if(i+r[i]>R) pos=i,R=i+r[i];
    51     }
    52     int res=0;
    53     for(int i=1;i<=len;++i) res=max(res,r[i]-1);
    54     return res;
    55 }
    56 int main()
    57 {
    58     int test=read();
    59     while(test--)
    60     {
    61         len=read();
    62         for(int i=1;i<=len;++i)
    63         str[i]=read();
    64         cout<<Manacher()<<endl;
    65     }
    66 }
    View Code

    C - Girls' research

    最长回文子串,需要记录子串下标

    用Manacher算法时,构造的新字符串奇数位为添加的符号,偶数位是原来的字符。

     1 #include<iostream>
     2 #include<sstream>
     3 #include<fstream>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<iomanip>
     7 #include<cstdlib>
     8 #include<cctype>
     9 #include<vector>
    10 #include<string>
    11 #include<cmath>
    12 #include<ctime>
    13 #include<stack>
    14 #include<queue>
    15 #include<map>
    16 #include<set>
    17 #define mem(a,b) memset(a,b,sizeof(a))
    18 #define random(a,b) (rand()%(b-a+1)+a)
    19 #define ll long long
    20 #define ull unsigned long long
    21 #define e 2.71828182
    22 #define Pi acos(-1.0)
    23 #define ls(rt) (rt<<1)
    24 #define rs(rt) (rt<<1|1)
    25 #define lowbit(x) (x&(-x))
    26 using namespace std;
    27 const int MAXN=1e6+5;
    28 char str[MAXN],nstr[MAXN<<1];
    29 int r[MAXN<<1];
    30 int len;
    31 int read()
    32 {
    33     int s=1,x=0;
    34     char ch=getchar();
    35     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
    36     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
    37     return x*s;
    38 }
    39 void Manacher()
    40 {
    41     for(int i=1;i<=len;++i) nstr[2*i-1]='%',nstr[2*i]=str[i];
    42     nstr[len=2*len+1]='%';
    43     int pos=0,R=0;
    44     for(int i=1;i<=len;++i)
    45     {
    46         if(i<R) r[i]=min(r[2*pos-i],R-i);
    47         else r[i]=1;
    48         while(i-r[i]>=1&&i+r[i]<=len&&nstr[i-r[i]]==nstr[i+r[i]]) r[i]++;
    49         if(i+r[i]>R) pos=i,R=i+r[i];
    50     }
    51     int po=0,ma=0;
    52 //    for(int i=1;i<=len;++i) cout<<"i: "<<i<<" r[i]: "<<r[i]<<'
    ';cout<<endl;
    53     for(int i=1;i<=len;++i) 
    54     if(r[i]>ma)
    55     {
    56         ma=r[i];
    57         po=i;
    58     }
    59     if(ma-1<2)
    60     {
    61         puts("No solution!");
    62         return ;
    63     }
    64 //    cout<<po<<' '<<ma<<endl;
    65     int num=ma/2-!(po%2);//两侧回文字符个数,不含中间字符 
    66     int l=po/2-num+po%2;
    67     int r=po/2+num;
    68     cout<<l-1<<' '<<r-1<<endl;
    69     for(int i=l;i<=r;++i)
    70     putchar(str[i]);
    71     putchar('
    ');
    72     
    73 }
    74 //a qqqzuiiuzaaaa
    75 int main()
    76 {
    77     char ch;
    78     while(scanf("%c",&ch)!=EOF)
    79     {
    80         scanf("%s",str+1);getchar();
    81         len=strlen(str+1);
    82         int del=ch-'a';
    83         for(int i=1;i<=len;++i) 
    84         if(str[i]-del<'a') str[i]=str[i]-del+26;
    85         else str[i]-=del;
    86         Manacher();
    87     }
    88     return 0;
    89 }
    View Code

    D - Making Huge Palindromes

    在一个串末尾添加尽量少的任意字符使得该串成为回文串。

     1 #include<iostream>
     2 #include<sstream>
     3 #include<fstream>
     4 #include<algorithm>
     5 #include<cstring>
     6 #include<iomanip>
     7 #include<cstdlib>
     8 #include<cctype>
     9 #include<vector>
    10 #include<string>
    11 #include<cmath>
    12 #include<ctime>
    13 #include<stack>
    14 #include<queue>
    15 #include<map>
    16 #include<set>
    17 #define mem(a,b) memset(a,b,sizeof(a))
    18 #define random(a,b) (rand()%(b-a+1)+a)
    19 #define ll long long
    20 #define ull unsigned long long
    21 #define e 2.71828182
    22 #define Pi acos(-1.0)
    23 #define ls(rt) (rt<<1)
    24 #define rs(rt) (rt<<1|1)
    25 #define lowbit(x) (x&(-x))
    26 using namespace std;
    27 const int MAXN=1e6+5;
    28 char str[MAXN],nstr[MAXN<<1];
    29 int r[MAXN<<1];
    30 int len;
    31 int read()
    32 {
    33     int s=1,x=0;
    34     char ch=getchar();
    35     while(!isdigit(ch)) {if(ch=='-') s=-1;ch=getchar();}
    36     while(isdigit(ch)) {x=10*x+ch-'0';ch=getchar();}
    37     return x*s;
    38 }
    39 int Manacher()
    40 {
    41     for(int i=1;i<=len;++i) nstr[2*i-1]='%',nstr[2*i]=str[i];
    42     nstr[len=2*len+1]='%';
    43     int pos=0,R=0;
    44     for(int i=1;i<=len;++i)
    45     {
    46         if(i<R) r[i]=min(r[2*pos-i],R-i);
    47         else r[i]=1;
    48         while(i-r[i]>=1&&i+r[i]<=len&&
    49             nstr[i-r[i]]==nstr[i+r[i]]) r[i]++;
    50         if(i+r[i]>R) pos=i,R=i+r[i];
    51     }
    52     int res=len;
    53     for(int i=1;i<=len;++i)
    54     {
    55         if(i+r[i]-1==len)
    56         res=min(res,(len-(2*r[i]-1))/2);
    57     }
    58     return res;
    59 }
    60 int main()
    61 {
    62 //    ios::sync_with_stdio(false);
    63 //    cin.tie(0);cout.tie(0);
    64     int test=read();
    65     for(int pp=1;pp<=test;++pp)
    66     {
    67         cout<<"Case "<<pp<<": ";
    68         cin>>str+1;
    69         len=strlen(str+1);
    70         cout<<Manacher()+strlen(str+1)<<endl;
    71     }
    72 }
    View Code
  • 相关阅读:
    《JS权威指南学习总结--6.6属性getter和setter》
    《JS权威指南学习总结--6.5枚举属性》
    django的模板系统
    django额外参数的传递和url命名
    python在图片上画矩形
    当爬虫遇到js加密
    php基础-7
    php基础-6
    php基础-5
    php基础-4
  • 原文地址:https://www.cnblogs.com/wangzhebufangqi/p/11523771.html
Copyright © 2020-2023  润新知