zoukankan      html  css  js  c++  java
  • hdu5782

    官方题解不是很详细

    首先有一个结论:若A=pa+sa B=pb+sb 

    A、B串循环同构,则可以构造一个可行方案(pa,sb) (sa,pb)中有一个是最长匹配,这个不难用反证法证明。

    对于s1,s2串,我们穷举s1的每一个后缀i,设s1[i..i+len-1]=s2[0..len-1] len是最长匹配

    那么不难得到,如果存在k使得k<=len且s1[0..i-1]=s2[k..k+i-1]

    那么,两串前缀s1[0..i+k-1]为循环同构

    因此我们预处理w[i][j]表示s1[0..i]=s2[j..j+i]是否相等,w数组我们可用bitset压位存储

    求出这个数组我们只需要建立后缀数组然后顺着height[]找即可

    下面我们在将变量代换,前缀p=i+k-1循环同构的条件为i-1<=p<=len+i-1且w[i-1][p]为1

    这个条件我们在压位的情况下可以用位运算处理

    问题得解

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 bitset<10000> w[10010],ans,pre[10010],tmp;
      5 char s2[20010],s1[20010];
      6 int d[20],lg[20010],h[20010],s[20010],rk[20010],sa[20010],x[20010],y[20010],a[20010];
      7 int f[20010][16],n;
      8 pair<int,int> q[20010];
      9 bool cmp(int a,int b,int j)
     10 {
     11     if (y[a]==y[b])
     12     {
     13         if (a+j<=n&&b+j<=n) return y[a+j]!=y[b+j];
     14         else if (a+j>n&&b+j>n) return 0;
     15         else return 1;
     16     }
     17     return y[a]!=y[b];
     18 }
     19 
     20 void suffix()
     21 {
     22     int m=28;
     23     memset(s,0,sizeof(s));
     24     for (int i=1; i<=n; i++) s[a[i]]++;
     25     for (int i=1; i<=m; i++) s[i]+=s[i-1];
     26     for (int i=n; i; i--) sa[s[a[i]]--]=i;
     27     int p=1; rk[sa[1]]=1;
     28     for (int i=2; i<=n; i++)
     29     {
     30         if (a[sa[i]]!=a[sa[i-1]]) ++p;
     31         rk[sa[i]]=p;
     32     }
     33     int j=1; m=p;
     34     while (m<n)
     35     {
     36         memcpy(y,rk,sizeof(rk));
     37         memset(s,0,sizeof(s));
     38         p=0;
     39         for (int i=n-j+1; i<=n; i++) x[++p]=i;
     40         for (int i=1; i<=n; i++)
     41             if (sa[i]>j) x[++p]=sa[i]-j;
     42         for (int i=1; i<=n; i++) s[rk[i]=y[x[i]]]++;
     43         for (int i=1; i<=m; i++) s[i]+=s[i-1];
     44         for (int i=n; i; i--) sa[s[rk[i]]--]=x[i];
     45         rk[sa[1]]=1; p=1;
     46         for (int i=2; i<=n; i++)
     47         {
     48             if (cmp(sa[i],sa[i-1],j)) ++p;
     49             rk[sa[i]]=p;
     50         }
     51         m=p; j<<=1;
     52     }
     53     p=0; h[1]=0;
     54     for (int i=1; i<=n; i++)
     55     {
     56         if (rk[i]==1) continue;
     57         int j=sa[rk[i]-1];
     58         while (i+p<=n&&j+p<=n&&a[i+p]==a[j+p]) ++p;
     59         h[rk[i]]=p;
     60         if (p) p--;
     61     }
     62 }
     63 
     64 int ask(int x,int y)
     65 {
     66     int k=lg[y-x+1];
     67     return min(f[x][k],f[y-d[k]+1][k]);
     68 }
     69 
     70 void rmq()
     71 {
     72     for (int i=1; i<=n; i++)
     73         f[i][0]=h[i];
     74     for (int j=1; j<=lg[n]; j++)
     75     {
     76         for (int i=1; i<=n; i++)
     77             if (i+d[j]-1<=n) f[i][j]=min(f[i][j-1],f[i+d[j-1]][j-1]);
     78             else break;
     79     }
     80 }
     81 
     82 int main()
     83 {
     84  //   freopen("1002.in","r",stdin);
     85     d[0]=1; lg[1]=0;
     86     for (int i=1; i<=15; i++)
     87     {
     88         d[i]=d[i-1]*2;
     89         for (int j=d[i-1]; j<=min(20005,d[i]-1); j++) lg[j]=i-1;
     90     }
     91     pre[0][0]=1;
     92     for (int i=1; i<10000; i++)
     93     {
     94         pre[i]=pre[i-1];
     95         pre[i][i]=1;
     96     }
     97     while (scanf("%s%s",s1,s2)!=EOF)
     98     {
     99         int l=strlen(s1);
    100         n=0;
    101         for (int i=0; i<l; i++) a[++n]=s1[i]-'a'+1;
    102         a[++n]=27;
    103         for (int i=0; i<l; i++) a[++n]=s2[i]-'a'+1;
    104         a[n+1]=0;
    105         suffix(); rmq();
    106         for (int i=0; i<l; i++) w[i].reset();
    107         int len=n,m=0;
    108         for (int i=rk[1]+1; i<=n; i++)
    109         {
    110             len=min(len,h[i]);
    111             if (!len) break;
    112             else if (sa[i]>l+1) q[++m]=make_pair(len-1,sa[i]-l-2);
    113         }
    114         len=h[rk[1]];
    115         for (int i=rk[1]-1; i; i--)
    116         {
    117             if (!len) break;
    118             else if (sa[i]>l+1) q[++m]=make_pair(len-1,sa[i]-l-2);
    119             len=min(len,h[i]);
    120         }
    121         sort(q+1,q+1+m);
    122         tmp.reset(); int j=m;
    123         for (int i=l-1; i>=0; i--)
    124         {
    125             while (j&&q[j].first==i) tmp[q[j--].second]=1;
    126             w[i]=tmp;
    127         }
    128         ans.reset();
    129         for (int i=0; i<l; i++)
    130         {
    131             int x=rk[i+1],y=rk[l+2];
    132             if (x>y) swap(x,y);
    133             len=ask(x+1,y);
    134             if (len)
    135             {
    136                 if (i) ans|=(pre[i-1]^pre[i+len-1])&(w[i-1]<<(i-1));
    137                 else ans|=pre[len-1];
    138             }
    139         }
    140         for (int i=0; i<l; i++)
    141             if (ans[i]) printf("1"); else printf("0");
    142         puts("");
    143     }
    144 }
    View Code
  • 相关阅读:
    不怕路长,只怕心老——走在IT行业的路上
    python中 r'', b'', u'', f'' 的含义
    WSGI接口
    HTTP协议简介
    Flask中的Session
    一个 android 开机自动启动功能的例子
    遍历 JObject各属性(CSharp2)
    ASP.NET 伪随机数函数避免重复一例
    浏览器环境下 ES6 的 export, import 的用法举例
    在浏览器环境使用js库(不用require功能)
  • 原文地址:https://www.cnblogs.com/phile/p/6446148.html
Copyright © 2011-2022 走看看