码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2019-09-09 22:25:16      阅读:126      评论:0      收藏:0      [点我收藏+]

标签:style   bsp   owb   scanf   void   mes   长度   name   set   

题意:给定两个长度相等的仅由小写字母组成的串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 }

 

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

标签:style   bsp   owb   scanf   void   mes   长度   name   set   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!