zoj4110 Strings in the Pocket(manacher)

传送:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012

题意:给定两个串$S$和$T$,可以翻转$S$串中的任意一个子段,得到$T$。问,可以翻转的方案书有多少?

数据范围:多组数据。$1\leq|S|\leq2\times10^5$,$\sum|S|\leq2\times10^7$。

分析:很明显需要分类讨论$S$与$T$比较的各种情况。

首先需要判断$S$串从左和从右找到与$T$开始不同的位置。

  1. $S$不可以翻转成$T$:就是指$S$串中不同的那一段不可以通过翻转得到$T$,方案数为0。
  2. $S$与$T$不同的“中间”那一段可以通过翻转得到对应$T$的那一段。这个时候需要向外扩展判断最长可以扩展到的位置。
  3. $S$与$T$完全相同,这个时候就需要通过manacher来求解整个串内回文子串的个数。

代码:

  1. 不分奇偶讨论的manacher
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=2e6+10;
 5 char S[maxn],T[maxn],s[maxn*2];
 6 int p[maxn*2],len;
 7 int init(){
 8     s[0]=s[1]=‘#‘;
 9     for (int i=0;i<len;i++){
10         s[i*2+2]=S[i];
11         s[i*2+3]=‘#‘;
12     }
13     len=len*2+2;
14     s[len]=0;
15 }
16 void manacher(){
17     int id,mx=0;
18     for (int i=1;i<len;i++){
19         if(i<mx) p[i]=min(p[(id<<1)-i],p[id]+id-i);
20         else p[i]=1;
21         while (s[i-p[i]]==s[i+p[i]]) p[i]++;
22         if (mx<i+p[i]){
23             id=i;mx=i+p[i];
24         }
25     }
26 }
27 int main(){
28     int t; scanf("%d",&t);
29     while (t--){
30         scanf("%s",S);
31         scanf("%s",T);
32         len=strlen(S);
33         int l=0,r=len-1; ll ans=0;
34         while (S[l]==T[l] && l<len) l++;
35         while (S[r]==T[r] && r>=0) r--;
36         if (l==r){printf("0\n"); continue;}
37         if (l<len){
38             ans=1;
39             for (int i=l;i<=r;i++)
40                 if (S[i]!=T[l+r-i]){
41                     ans=0; break;
42                 }
43             if (ans){
44                 ans=1;
45                 l--;r++;
46                 while (l>=0 && r<len && S[l]==T[r] && S[r]==T[l]){
47                     l--;r++;ans++;
48                 }
49             }
50             printf("%d\n",ans);
51         }
52         else{
53             init();
54             manacher(); ans=1;
55             for (int i=0;i<len;i++) ans+=(p[i]/2);
56             printf("%lld\n",ans-1);
57         }
58     }
59     return 0;
60 }

  2.分奇偶讨论的manacher

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=2e6+10;
 5 char S[maxn],T[maxn];
 6 int odd[maxn],eve[maxn],len;
 7 ll manacher(){
 8     int l=-1,r=-1,x;
 9     ll ans=0;
10     for(int i=0;i<len;i++)
11     {
12         if (i>r) x=1;
13         else x=min(odd[l+r-i],r-i);
14         while (i-x>=0 && i+x<len && S[i-x]==S[i+x]) x++;
15         odd[i]=x;
16         ans+=x;
17         if (i+x-1>r) {r=i+x-1;l=i-x+1;}
18     }
19     l=r=-1;
20     for(int i=0;i<len;i++)
21     {
22         if(i>r) x=0;
23         else x=min(eve[l+r-i+1],r-i+1);
24         while (i-x-1>=0 && i+x<len && S[i-x-1]==S[i+x]) x++;
25         eve[i]=x;
26         ans+=x;
27         if (i+x>=r) {l=i-x;r=i+x-1;}
28     }
29     return ans;
30 }
31 int main(){
32     int t; scanf("%d",&t);
33     while (t--){
34         scanf("%s",S);
35         scanf("%s",T);
36         len=strlen(S);
37         int l=0,r=len-1; ll ans=0;
38         while (S[l]==T[l] && l<len) l++;
39         while (S[r]==T[r] && r>=0) r--;
40         if (l==r){printf("0\n"); continue;}
41         if (l<len){
42             ans=1;
43             for (int i=l;i<=r;i++)
44                 if (S[i]!=T[l+r-i]){
45                     ans=0; break;
46                 }
47             if (ans){
48                 ans=1;
49                 l--;r++;
50                 while (l>=0 && r<len && S[l]==T[r] && S[r]==T[l]){
51                     l--;r++;ans++;
52                 }
53             }
54             printf("%d\n",ans);
55         }
56         else{
57             ans=manacher();
58             printf("%lld\n",ans);
59         }
60     }
61     return 0;
62 }

原文地址:https://www.cnblogs.com/changer-qyz/p/10792437.html

时间: 2024-10-07 18:17:47

zoj4110 Strings in the Pocket(manacher)的相关文章

HDU----(3294)Girls&#39; research(manacher)

Girls' research Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 537    Accepted Submission(s): 199 Problem Description One day, sailormoon girls are so delighted that they intend to research abo

hdu3294Girls&#39; research(manacher)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3294 题目不难,感觉输出比较麻烦. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int maxn=2000010; 6 char s[maxn<<1]; 7 int r[maxn<<1]; 8 char ans[

HDU 4513 吉哥系列故事——完美队形II(Manacher)

Problem Description 吉哥又想出了一个新的完美队形游戏! 假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形: 1.挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的: 2.左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意: 3.从左到中间那

O(n)回文子串(Manacher)算法

O(n)回文子串(Manacher)算法 资料来源网络 参见:http://www.felix021.com/blog/read.php?2040 问题描述: 输入一个字符串,求出其中最大的回文子串.子串的含义是:在原串中连续出现的字符串片段.回文的含义是:正着看和倒着看相同,如abba和yyxyy. 解析: 这里介绍O(n)回文子串(Manacher)算法 算法基本要点:首 先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度:在每个字符的两边都插入一个特殊的符号.比

算法导论:回文子串(Manacher)算法 ,O(n)时间效率实现

问题描述: 输入一个字符串,求出其中最大的回文子串.子串的含义是:在原串中连续出现的字符串片段.回文的含义是:正着看和倒着看相同,如abba和yyxyy. 解析: 这里介绍O(n)回文子串(Manacher)算法 算法基本要点:首先用一个非常巧妙的方式,将所有可能的奇数/偶数长度的回文子串都转换成了奇数长度: 在每个字符的两边都插入一个特殊的符号.比如 abba 变成 #a#b#b#a#, aba变成 #a#b#a#. 为了进一步减少编码的复杂度,可以在字符串的开始加入另一个特殊字符,这样就不用

Strings in the Pocket(马拉车+字符串判断)

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=6012 BaoBao has just found two strings s and in his left pocket, where indicates the -th character in string , and indicates the -th character in string . As BaoBao is bored, he decides to

ZOJ4110 Strings in the Pocket(2019浙江省赛)

给出两个字符串,询问有多少种反转方法可以使字符串1变成字符串2. 如果两个串相同,就用马拉车算法找回文串的数量~ 如果两个串不同,从前往后找第一个不同的位置l,从后往前找第二个不同的位置r,反转l和r,判断是否成功~ 如果不成功,记为0 如果成功,以l和r为起点判断是否能反转,记录次数 #include<bits/stdc++.h> using namespace std; const int maxn=2e6+100; typedef long long ll; char s1[maxn];

CC 3-Palindromes(manacher)

传送门:3-Palindromes 题意:求为回文串且能整除3且不前导0的子串个数. 分析:由 manacher算法O(N)可算出以i为坐标的最长为p[i]回文子串,且Si-k,Si-k+1......Si+k-1,Si+k(0<k<p[i])全为回文串. 又知,能整除3的整数数位和也能整除3,那么只要Si-k,Si-k+1......Si+k-1,Si+k和整除3即可. 由回文串对称性知Si-k==Si-k,那么只要Si-k..Si-1这段中模3余数与Si模3余数相同,Si-k...Si+k

最长回文(Manacher)

HOT~ 杭电2015级新生如何加入ACM集训队? 最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12244    Accepted Submission(s): 4501 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正反读都是一样的字符