• Gym


    题面

    题意:给你2个串(长度1e6),在第一个串里找“s1s2s3”,第二个串里找“s4”,拼接后,是一个回文串,求方案数

    题解:知道s1和s4回文,s2和s3回文,所以我们枚举s1的右端点,s1的长度乘以s2起始点为左边界的回文串的数量,累加就是答案。

    所以先求s1,再求以每个点为左边界的回文串的数量

    就是求每个后缀匹配第二个串的LCP(扩展kmp,或者hash+二分)二的话,后面部分用(Manacher+前缀和)就可以解决

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1e6+50;
      4 char str[maxn*2],t[maxn*2],s[maxn*2];
      5 int dp[maxn*2],dpnext[maxn*2],dpret[maxn*2],suffix[maxn*2],last[maxn];
      6 void manacher(char tmp[],int length,int rad[])
      7 {
      8     for(int i=1,j=0,k;i<length;i+=k)
      9     {
     10         while(tmp[i-j-1]==tmp[i+j+1]) j++;
     11         rad[i]=j;
     12         for(k=1;k<=rad[i]&&rad[i-k]!=rad[i]-k;++k)
     13         {
     14             rad[i+k]=min(rad[i-k],rad[i]-k);
     15         }
     16         j=max(j-k,0);
     17     }
     18 }
     19 void ExtendedKMP(char *a,char *b,int M,int N,int *Next,int *ret)
     20 {
     21     int i,j,k;
     22     for(j=0;1+j<M&&a[j]==a[1+j];j++);
     23     Next[1]=j;
     24     k=1;
     25     for(i=2;i<M;i++)
     26     {
     27         int Len=k+Next[k],L=Next[i-k];
     28         if(L<Len-i)
     29         {
     30             Next[i]=L;
     31         }
     32         else
     33         {
     34             for(j=max(0,Len-i);i+j<M&&a[j]==a[i+j];j++);
     35             Next[i]=j;
     36             k=i;
     37         }
     38     }
     39     for(j=0;j<N&&j<M&&a[j]==b[j];j++);
     40     ret[0]=j;
     41     k=0;
     42     for(i=1;i<N;i++)
     43     {
     44         int Len=k+ret[k],L=Next[i-k];
     45         if(L<Len-i)
     46         {
     47             ret[i]=L;
     48         }
     49         else
     50         {
     51             for(j=max(0,Len-i);j<M&&i+j<N&&a[j]==b[i+j];j++);
     52             ret[i]=j;
     53             k=i;
     54         }
     55     }
     56 }
     57 int main()
     58 {
     59     int i,j,k,n,m,lens,lent;
     60     scanf(" %s",str);
     61     scanf(" %s",t);
     62     lens=strlen(str);
     63     lent=strlen(t);
     64     reverse(str,str+lens);
     65     s[0]='(';s[1]='#';
     66     for(i=0,j=2;i<lens;i++,j+=2)
     67     {
     68         s[j]=str[i];
     69         s[j+1]='#';
     70     }
     71     n=lens;
     72     lens=lens*2+3;
     73     s[lens-1]=')';
     74     manacher(s,lens,dp);
     75     ExtendedKMP(t,str,lent,n,dpnext,dpret);
     76     suffix[lens]=0;
     77     memset(last,0,sizeof(last));
     78     for(i=2;i<lens-2;i++)
     79     {
     80         long long maxdis;
     81         if(i%2==0)
     82         {
     83             maxdis=i/2+dp[i]/2-1;
     84             last[maxdis]++;
     85             last[i/2-2]--;
     86         }
     87         else
     88         {
     89             maxdis=i/2+dp[i]/2-1;
     90             if(dp[i]/2>0)
     91             {
     92                 last[maxdis]++;
     93                 last[i/2-1]-- ;
     94             }
     95         }    
     96     }
     97     suffix[n]=0;
     98     for(i=n-1;i>=0;i--)
     99         suffix[i]=suffix[i+1]+last[i];
    100     long long ans=0;
    101     for(i=0;i<n;i++)
    102     {
    103         long long len=dpret[i];
    104         ans=ans+len*(suffix[i-1]);
    105     }
    106     printf("%lld
    ",ans);
    107 }
  • 相关阅读:
    单选多选样式写法
    深拷贝方法
    防抖和节流的实现
    yarn 常用指令
    前端性能监控
    全表 or 索引
    Order by
    DINSTINCT
    智力题
    概率问题
  • 原文地址:https://www.cnblogs.com/qywhy/p/10102954.html
Copyright © 2020-2023  润新知