zoukankan      html  css  js  c++  java
  • 【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("
    ");
    100     if(f[n]==1e9)
    101     {
    102         printf("-1
    ");
    103         return 0;
    104     }
    105     printf("%d
    ",f[n]);
    106     int k=n;
    107     while(k)
    108     {
    109         int t=pre[k];
    110         if(t<k-2) printf("%d %d
    ",t/2+1,k/2);
    111         k=t;
    112     }
    113 
    114     return 0;
    115 }
  • 相关阅读:
    在WPF中添加Windows Form控件
    LIST对象排序问题
    C# TreeView树节点上下移动
    C# listbox的上下移动,拖动排序,两个listbox相互拖动
    Nmap 扫描并生成HTML报告
    Windows 10 系统精简方案参考
    Windows10 子系统 Ubuntu安装
    VS2012 RC页面检查器
    新增功能.NET 框架 4.5 RC
    PowerPoint Storyboarding:Visual Studio 2012 RC带给开发者的秘密杀器
  • 原文地址:https://www.cnblogs.com/myx12345/p/11494497.html
Copyright © 2011-2022 走看看