传送: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

zoj4110 Strings in the Pocket(manacher)相关推荐

  1. 最长回文字符串——马拉车(Manacher)算法

    最长回文字符串--马拉车(Manacher)算法 说来惭愧,都快要毕业了才写第一篇博客... 回文串 回文串呢,就是在一个字符串中,左半部分和右半部分是镜像对称的字符串,比如abcba,就是一个已c为 ...

  2. 算法练习day18——190409(Manacher)

    1.Manacher算法 一个串中,找到最长的回文子串. 1.1 暴力解决 得解决长度为奇数的回文和长度为偶数的回文. 1.1.1 奇回文 i位置自己肯定构成回文:长度为1 i+1位置和i-1位置相不 ...

  3. 小G的项链(Manacher)

    我看网上也没有写这个题的,顺便写一下(可能是大佬都觉得太简单了 ) 链接:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO ...

  4. 马拉车(manacher)算法——最长回文(hdu3068)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3068 题目描述: Problem Description 给出一个只由小写英文字符a,b,c...y ...

  5. 彻底搞懂马拉车(Manacher)

    Manacher算法,又叫"马拉车",它可以在时间复杂度和空间复杂度都是O(n)的情况下,求出一个字符串的最长回文串长度. 回文串的基本解法 以每一个点为中心对称点,每次保留最长回 ...

  6. 马拉车(manacher)算法

    本篇博客基于这篇博客的理解. 马拉车可以在线性时间内找到字符串的最大回文子串. 先来说说它是如何工作的. 其实本质上马拉车算是一个很优美的暴力算法,它从头到尾遍历一遍字符串的每一个元素,然后把当前遍历 ...

  7. KMP BFPRT 马拉车(Manacher)

    目录 1.KMP: Ⅰ.某个字符的"指标" ⅠⅠ.KMP的使用方法: ⅠⅠⅠ.理由1: ⅠⅤ.理由2: Ⅴ."指标的获取": ⅤⅠ.代码部分: 2.BFPRT( ...

  8. 马拉车算法(manacher)求最长回文子串

    关于回文字符串的概念大家可以大致去搜索一下,这里不赘述. 一.解题思路 当前字符串 最长回文子串: 思路实际上很简单,就是遍历每一个元素,然后分别以这个元素为中心,向两边扩展,比如说现在i = 4,那 ...

  9. 【2019浙江省赛 - K 】Strings in the Pocket(马拉车,思维)

    题干: BaoBao has just found two strings  and  in his left pocket, where  indicates the -th character i ...

最新文章

  1. 支付宝app支付总结
  2. RTlinux3.2安装
  3. 检查Android应用程序是否在后台运行
  4. 一次微服务与IoT的深度探秘与实战
  5. Android 4.4沉浸式状态栏的实现
  6. Android在Shell环境下运行Linux命令
  7. Ubuntu18.04安装Gaussian16和GaussView 6
  8. python__和_区别_【Python】对_和__差别的理解
  9. sparkshelljarlib_spark-submit 应用程序第三方jar文件
  10. 线性瘤是良性吗_良性聚会:露营者如何构建开放源代码工具来解决时区
  11. mysql定义和调用存储过程
  12. gcc -o sqlite3 shell.c sqlite3.c -ldl -lpthread
  13. 使用自定义手势处理器-陈鹏
  14. VS2013 MFC 中DLL链接库断点不能命中的解决方案总结
  15. HUSTOJ(2019)在线判题系统的搭建
  16. Cesium加载OSGB数据
  17. linux服务器安装cuda,在Linux下安装Cuda5
  18. AI安全技术总结与展望
  19. Windows相关产品密钥
  20. 品荔枝赏文化,美丽乡村不一样的嘉年华

热门文章

  1. html资源加载,如何加载文件资源 (HTML)
  2. c#结合emgucv进行人脸检测_人脸识别与测温结合在办公场景有哪些应用?
  3. layui fixbar 返回顶部_FANUC 数控系统机床返回参考点功能的应用研究
  4. seaborn系列 (17) | 回归模型图lmplot()
  5. 5笔涂出一只3D猫咪模型,可跑可跳无需手动绑定骨骼,新鬼畜素材get丨浙大开源...
  6. 72岁奶奶在抖音教物理火了,百万粉丝追更,网友:小时候要有这种老师就好了...
  7. 速来!亚马逊云科技AI盛会开源专场吹响集结号
  8. Nature今年首次撤稿给了微软:研究团队成员自曝删改不利数据,量子计算重大进展是假的...
  9. 3个可以写进简历的京东AI NLP项目实战,走完这五步就是Top算法工程师
  10. 斩获23项冠军,日均调用破万亿!百度交出年度AI成绩单:语音语言领衔技术突破,国产自研成大趋势...