• [HAOI2016]找相同字符


    题目描述

    给定两个字符串,求出在两个字符串中各取出一个子串使得这两个子串相同的方案数。两个方案不同当且仅当这两个子串中有一个位置不同。

    输入输出格式

    输入格式:

    两行,两个字符串s1,s2,长度分别为n1,n2。1 <=n1, n2<= 200000,字符串中只有小写字母

    输出格式:

    输出一个整数表示答案

    输入输出样例

    输入样例#1: 复制
    aabb
    bbaa
    输出样例#1: 复制
    10
    将两串合并,中间加一个分隔符
    先求出后缀数组和LCP的height数组
    要求的就是后缀数组中不属于同一串的后缀的LCP
    对于每一个(l,r)找到最小值位置minpos
    在两边找来自两个不同串后缀数,分两种情况统计
    然后分两边(l,minpos-1),(minpos,r)
    用线段树维护
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 typedef long long lol;
      9 struct Seg
     10 {
     11   lol cnt[3];
     12   int x,pos;
     13 }t[2000001];
     14 struct Data
     15 {
     16   int l,r;
     17 };
     18 int SA[500001],c[500001],rank[500001],x[500001],y[500001],len1,len2,n,m,s[500001];
     19 char s1[500001],s2[500001];
     20 queue<Data>Q;
     21 lol ans,h[500001];
     22 void build(int rt,int l,int r)
     23 {
     24   if (l==r)
     25     {
     26       if (SA[l]<len1) t[rt].cnt[1]=1;
     27       if (SA[l]>len1) t[rt].cnt[2]=1;
     28       t[rt].x=h[l];
     29       t[rt].pos=l;
     30       return;
     31     }
     32   int mid=(l+r)>>1;
     33   build(rt<<1,l,mid);
     34   build(rt<<1|1,mid+1,r);
     35   t[rt].cnt[1]=t[rt<<1].cnt[1]+t[rt<<1|1].cnt[1];
     36   t[rt].cnt[2]=t[rt<<1].cnt[2]+t[rt<<1|1].cnt[2];
     37   if (t[rt<<1].x<=t[rt<<1|1].x)
     38     {
     39       t[rt].pos=t[rt<<1].pos;
     40       t[rt].x=t[rt<<1].x;
     41     }
     42   else
     43     {
     44       t[rt].pos=t[rt<<1|1].pos;
     45       t[rt].x=t[rt<<1|1].x;
     46     }
     47 }
     48 lol query_cnt(int rt,int l,int r,int L,int R,int x)
     49 {
     50   if (l>=L&&r<=R)
     51     {
     52       return t[rt].cnt[x];
     53     }
     54   int mid=(l+r)>>1;
     55   lol s=0;
     56   if (L<=mid) s+=query_cnt(rt<<1,l,mid,L,R,x);
     57   if (R>mid) s+=query_cnt(rt<<1|1,mid+1,r,L,R,x);
     58   return s;
     59 }
     60 int query_min(int rt,int l,int r,int L,int R)
     61 {
     62   if (l>=L&&r<=R)
     63     {
     64       return t[rt].pos;
     65     }
     66   int mid=(l+r)>>1,s1=-1,s2=-1;
     67   if (L<=mid) s1=query_min(rt<<1,l,mid,L,R);
     68   if (R>mid) s2=query_min(rt<<1|1,mid+1,r,L,R);
     69   if (s2==-1) return s1;
     70   if (s1==-1) return s2;
     71   if (h[s2]>=h[s1]) return s1;
     72   return s2;
     73 }
     74 void radix_sort()
     75 {int i;
     76   for (i=0;i<m;i++)
     77     c[i]=0;
     78   for (i=0;i<n;i++)
     79     c[x[y[i]]]++;
     80   for (i=1;i<m;i++)
     81     c[i]+=c[i-1];
     82   for (i=n-1;i>=0;i--)
     83     SA[--c[x[y[i]]]]=y[i];
     84 }
     85 void build_SA()
     86 {int i,j,k,p;
     87   for (i=0;i<n;i++)
     88     x[i]=s[i],y[i]=i;
     89   m=1000;
     90   radix_sort();
     91   for (k=1;k<=n;k<<=1)
     92     {
     93       p=0;
     94       for (i=n-k;i<n;i++)
     95     y[p++]=i;
     96       for (i=0;i<n;i++)
     97     if (SA[i]>=k) y[p++]=SA[i]-k;
     98       radix_sort();
     99       p=1;
    100       swap(x,y);
    101       x[SA[0]]=0;
    102       for (i=1;i<n;i++)
    103     x[SA[i]]=((y[SA[i]]==y[SA[i-1]])&&((SA[i]+k<n?y[SA[i]+k]:-1)==(SA[i-1]+k<n?y[SA[i-1]+k]:-1)))?p-1:p++;
    104       if (p>=n) break;
    105       m=p;
    106     }
    107   for (i=0;i<n;i++)
    108     rank[SA[i]]=i;
    109   int L=0;
    110   for (i=0;i<n;i++)
    111     if (rank[i]>0)
    112       {
    113     if (L>0) L--;
    114     j=SA[rank[i]-1];
    115     while (i+L<n&&j+L<n&&(s[i+L]==s[j+L])) L++;
    116     h[rank[i]]=L;
    117       }
    118 }
    119 int main()
    120 {int i;
    121   cin>>s1>>s2;
    122   len1=strlen(s1),len2=strlen(s2);
    123   for (i=0;i<len1;i++)
    124     s[i]=(int)s1[i];
    125   s[len1]=(int)'#';
    126   for (i=0;i<len2;i++)
    127     s[i+len1+1]=(int)s2[i];
    128   n=len1+len2+1;
    129   build_SA();
    130   build(1,0,n-1);
    131   Q.push((Data){0,n-1});
    132   while (Q.empty()==0)
    133     {
    134       Data u=Q.front();
    135       Q.pop();
    136       int l=u.l,r=u.r;
    137       int minpos=query_min(1,0,n-1,l+1,r);
    138       //cout<<l<<' '<<r<<' '<<h[minpos]<<endl;
    139       if (l<minpos-1) Q.push((Data){l,minpos-1});
    140       if (minpos<r) Q.push((Data){minpos,r});
    141       ans+=query_cnt(1,0,n-1,l,minpos-1,1)*query_cnt(1,0,n-1,minpos,r,2)*h[minpos];
    142       ans+=query_cnt(1,0,n-1,l,minpos-1,2)*query_cnt(1,0,n-1,minpos,r,1)*h[minpos];
    143     }
    144   cout<<ans;
    145 }
  • 相关阅读:
    TFS客户端登录用户修改
    MySQL查看最大连接数和修改最大连接数
    LR代理录制方法
    redis desktop manage安装和连接redis
    eclipse内存分析工具MAT
    NMON中的参数指标详解
    LoadRunner设置用户响应时间百分比
    性能测试中关键指标的监控与分析
    内存泄露检查
    tomcat参数设置
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8477668.html
Copyright © 2020-2023  润新知