zoukankan      html  css  js  c++  java
  • 加密

    【问题描述】
    有一种不讲道理的加密方法是: 在字符串的任意位置随机插入字符。 相应的,
    不讲道理的解密方法就是从字符串中恰好删去随机插入的那些字符。
    给定原文?和加密后的字符串?,求?有多少子串可以通过解密得到原文?。
    【输入格式】
    输入第一行包含一个字符串?,第二行包含一个字符串?。
    【输出格式】
    输出一行,包含一个整数,代表可以通过解密得到原文的?的子串的数量。
    【样例输入】
    abcabcabc
    cba
    【样例输出】
    9
    【样例解释】
    用[?,?]表示子串开头结尾的下标(从 0 开始编号) ,这 9 种方案是:
    [0,6],[0,7],[0,8],[1,6],[1,7],[1,8],[2,6],[2,7],[2,8]
    【数据规模和约定】
    30%的数据,|?| 1000。
    对于100%的数据,1 ≤ |?| ≤ 300,000,1 ≤ ? ≤ 200。

    /*
      这道题想出了怎么做,然而写挂了~
      预处理出t数组中每个元素对应的与它邻近的a-z分别在哪儿,然后直接模拟可做。
      一开始我预处理的与它邻近的并且与它相同的元素距离是0,所以后来模拟的时候碰到s数组类似于“abbc”这种有连续相同字符的就挂了。
      本来自己造了几组数据,和暴力的结果都一样,然而没有造到这种数据,以后对拍一定要写对拍程序!!!
    */
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #define M 300010
    #define N 1010
    #define lon long long
    using namespace std;
    char t[M],s[N];
    int near[M][30],m,n,head[M],tail[M],num;
    void work(){
        int p=-1;lon tot=0;
        for(int i=0;i<m;i++){
            if(t[i]!=s[0])continue;
            tot+=(lon)(i-p)*(lon)(m-i);
            p=i;
        }
        cout<<tot;
    }
    int main(){
        freopen("encrypt.in","r",stdin);
        freopen("encrypt.out","w",stdout);
        cin>>t>>s;
        m=strlen(t);n=strlen(s);
        if(n==1){
            work();return 0;
        }
        for(int i=1;i<=26;i++) near[m][i]=M;
        for(int i=m-1;i>=0;i--){
            for(int j=1;j<=26;j++){
                if(t[i]==j+'a'-1) near[i][j]=0;
                else if(near[i+1][j]==M) near[i][j]=M;
                else near[i][j]=near[i+1][j]+1;
            }
        }
        for(int i=0;i<=m;i++){
            for(int j=1;j<=26;j++){
                if(!near[i][j])
                    near[i][j]=near[i+1][j]+1;
            }
        }
        for(int i=0;i<m;i++){
            if(t[i]!=s[0])continue;
            int j=i,sum=1;
            while(1){
                j+=near[j][s[sum]-'a'+1];
                sum++;
                if(j>=M||sum==n)break;
            }
            if(sum==n&&j<M-10){
                head[++num]=i;tail[num]=j;
            }
        }
        lon tot=0;head[0]=-1;
        for(int i=1;i<=num;i++){
            tot+=(lon)(head[i]-head[i-1])*(lon)(m-tail[i]);
        }
        cout<<tot;
        return 0;
    }
  • 相关阅读:
    HDU 1874 畅通工程续(dijkstra)
    HDU 2112 HDU Today (map函数,dijkstra最短路径)
    HDU 2680 Choose the best route(dijkstra)
    HDU 2066 一个人的旅行(最短路径,dijkstra)
    关于测评机,编译器,我有些话想说
    测评机的优化问题 时间控制
    CF Round410 D. Mike and distribution
    数字三角形2 (取模)
    CF Round410 C. Mike and gcd problem
    CF Round 423 D. High Load 星图(最优最简构建)
  • 原文地址:https://www.cnblogs.com/harden/p/6057042.html
Copyright © 2011-2022 走看看