【CF906E】Reverses(回文自动机,最小回文分割)

题意:给定两个长度相等的仅由小写字母组成的串A和B,问在A中最少选择多少段互不相交的子串进行翻转能使A和B相同

len<=5e5

思路:构造新串S=a[1]b[1]a[2]b[2]...a[n]b[n]

问题等价于求S的最小回文分割,其中需要每一段的长度都为偶数,注意长度为2的相当于没有翻转

把板子稍加修改即可

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 typedef pair<ll,int>P;
 11 #define N  1100010
 12 #define M  210000
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pi acos(-1)
 17 #define mem(a,b) memset(a,b,sizeof(a))
 18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 20 #define lowbit(x) x&(-x)
 21 #define Rand (rand()*(1<<16)+rand())
 22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 23 #define ls p<<1
 24 #define rs p<<1|1
 25
 26 const int MOD=998244353,inv2=(MOD+1)/2;
 27       double eps=1e-6;
 28       int INF=1<<29;
 29       ll inf=5e13;
 30       int dx[4]={-1,1,0,0};
 31       int dy[4]={0,0,-1,1};
 32
 33
 34 char a[N],b[N];
 35 int s[N];
 36 int n;
 37 int q,p,id,num[N],F[N],f[N],_f[N],pre[N],len[N],sk[N],df[N],t[N][26];
 38
 39 struct pam
 40 {
 41     void add(int x,int n)
 42     {
 43             while(s[n-len[p]-1]!=s[n]) p=F[p];
 44         if(!t[p][x])
 45         {
 46                 int q=++id,k=F[p];
 47             len[q]=len[p]+2;
 48             while(s[n-len[k]-1]!=s[n]) k=F[k];
 49             F[q]=t[k][x];
 50             t[p][x]=q;
 51             df[q]=len[q]-len[F[q]];
 52             sk[q]=(df[q]==df[F[q]]?sk[F[q]]:F[q]);
 53         }
 54         p=t[p][x];
 55     }
 56 }pam;
 57
 58 int read()
 59 {
 60    int v=0,f=1;
 61    char c=getchar();
 62    while(c<48||57<c) {if(c==‘-‘) f=-1; c=getchar();}
 63    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 64    return v*f;
 65 }
 66
 67 int main()
 68 {
 69     //freopen("1.in","r",stdin);
 70     //freopen("1.out","w",stdout);
 71     scanf("%s",a+1);
 72     int m=strlen(a+1);
 73     scanf("%s",b+1);
 74     int n=0;
 75     rep(i,1,m)
 76     {
 77         s[++n]=a[i]-‘a‘;
 78         s[++n]=b[i]-‘a‘;
 79     }
 80     s[n+1]=s[0]=100;
 81     id=F[0]=1; len[1]=-1; _f[0]=1;
 82     rep(i,1,n) f[i]=1e9;
 83     rep(i,1,n)
 84     {
 85         pam.add(s[i],i);
 86         for(int x=p;x;x=sk[x])
 87         {
 88             _f[x]=i-len[sk[x]]-df[x];
 89             if(df[F[x]]==df[x]&&f[_f[x]]>f[_f[F[x]]]) _f[x]=_f[F[x]];
 90             if(i%2==0&&f[i]>f[_f[x]]+1) f[i]=f[_f[x]]+1,pre[i]=_f[x];
 91             if(i%2==0&&s[i]==s[i-1]&&f[i-2]<f[i])
 92             {
 93                 f[i]=f[i-2];
 94                 pre[i]=i-2;
 95             }
 96         }
 97     }
 98     //rep(i,1,n) printf("%d ",s[i]);
 99     //printf("\n");
100     if(f[n]==1e9)
101     {
102         printf("-1\n");
103         return 0;
104     }
105     printf("%d\n",f[n]);
106     int k=n;
107     while(k)
108     {
109         int t=pre[k];
110         if(t<k-2) printf("%d %d\n",t/2+1,k/2);
111         k=t;
112     }
113
114     return 0;
115 }

原文地址:https://www.cnblogs.com/myx12345/p/11494497.html

时间: 2024-10-29 15:32:58

【CF906E】Reverses(回文自动机,最小回文分割)的相关文章

Reverses CodeForces - 906E (最小回文分解)

题意: 给你两个串s和t,其中t是由s中选择若干个不相交的区间翻转得到的,现在要求求出最少的翻转次数以及给出方案. 1≤|s|=|t|≤500000 题解: 我们将两个字符串合成成T=s1t1s2t2...sntn T=s1t1s2t2...sntn 那么问题就是最少要把整个字符串T 拆分成若干个偶数长度(并且长度大于2)的回文串.长度是2的表示没有反转.然后就变成了最小回文分解模型 ,然后直接上板子. 最小回文分解 论文在此 1 #include <set> 2 #include <m

【回文自动机】bzoj3676 [Apio2014]回文串

回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i)代表个数(要最后在fail树上dp一遍方可). 答案直接枚举一遍结点,然后用len(i)*cnt(i),取最大者即可. 回文自动机是非常优越的数据结构,可惜比manacher多一个字符集的空间-- #include<cstdio> #include<cstring> #include

【字符串】回文自动机资料

转自:http://blog.csdn.net/u013368721/article/details/42100363 今天我们来学习一个神奇的数据结构:Palindromic Tree.中译过来就是——回文树. 那么这个回文树有何功能? 假设我们有一个串S,S下标从0开始,则回文树能做到如下几点: 1.求串S前缀0~i内本质不同回文串的个数(两个串长度不同或者长度相同且至少有一个字符不同便是本质不同) 2.求串S内每一个本质不同回文串出现的次数 3.求串S内回文串的个数(其实就是1和2结合起来

回文树或者回文自动机,及相关例题

回文树简述 在大部分说法中,回文树与回文自动机指的是一个东西: 回文树是对一个字符串,基于自动机思想构建的处理回文问题的树形结构: 回文树是对着一个单串建立的: 于是他主要用于计数(回文子串种类及个数) 基本建立思路是先建立其前缀的回文树,然后每加上一个字符,统计影响: 回文树存在fail指针但一般不承接字符串匹配问题: (回文树大概可以判定一个回文串是不是一个串的子串,但KMP之类的可以做得更好) 构建好的回文树,是这样的: (好难看) 可看出: 存在两个树结构,分别记录奇数|偶数长度的回文:

【bzoj3676】[Apio2014]回文串 回文自动机

题目描述 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最大出现值. 输入 输入只有一行,为一个只包含小写字母(a -z)的非空字符串s. 输出 输出一个整数,为逝查回文子串的最大出现值. 样例输入 [样例输入l] abacaba [样例输入2] www 样例输出 [样例输出l] 7 [样例输出2] 4 题解 回文自动机裸题 关于PAM个人暂时理解不是很深入,挖坑待填. 本题只需要统计fail树的子树大小,再

[BZOJ4044]Virus synthesis 回文自动机的DP

4044: [Cerc2014] Virus synthesis Time Limit: 20 Sec  Memory Limit: 128 MB Description Viruses are usually bad for your health. How about fighting them with... other viruses? In this problem, you need to find out how to synthesize such good viruses. W

Palindromic Tree 回文自动机-回文树 例题+讲解

---恢复内容开始--- 回文树,也叫回文自动机,是2014年被西伯利亚民族发明的,其功能如下: 1.求前缀字符串中的本质不同的回文串种类 2.求每个本质不同回文串的个数 3.以下标i为结尾的回文串个数/种类 4.每个本质不同回文串包含的本质不同回文串种类 (本文参考自Palindromic Tree——回文树[处理一类回文串问题的强力工具],Palindromic Tree 回文自动机-回文树 解决回文串的神器) 下面介绍一些数组的意义 next[][]类似于字典树,指向当前字符串在两段同时加

【CF932G】Palindrome Partition 回文自动机

[CF932G]Palindrome Partition 题意:给你一个字符串s,问你有多少种方式,可以将s分割成k个子串,设k个子串是$x_1x_2...x_k$,满足$x_1=x_k,x_2=x_{k-1}...x_i=x{k-i+1}$. $|s|\le 10^6$ 题解:设字符串的长度为n,考虑字符串$T=s_1s_ns_2s_{n-1}...$.问题就转化成了:求将原串划分成若干个长度为偶数的回文子串的方案数. 首先我们有一种暴力的想法,设f[i]表示将前i个字符分成若干个回文子串的方

【XSY2715】回文串 树链剖分 回文自动机

题目描述 有一个字符串\(s\),长度为\(n\).有\(m\)个操作: \(addl ~c\):在\(s\)左边加上一个字符\(c\) \(addr~c\):在\(s\)右边加上一个字符 \(transl~l_1~r_1~l_2~r_2\):有两个\(s\)的子串\(s_1=s[l_1\ldots r_1],s_2=s[l_2\ldots r_2]\).你要把\(s_1\)变成\(s_2\).每次允许在左边加一个字符或删一个字符.要求操作次数最少.定义一个字符串是好的当且仅当这个字符串是回文串