加密(模拟)

【问题描述】


有一种不讲道理的加密方法是: 在字符串的任意位置随机插入字符。 相应的,
不讲道理的解密方法就是从字符串中恰好删去随机插入的那些字符。
给定原文?和加密后的字符串?,求?有多少子串可以通过解密得到原文?。


【输入格式】


输入第一行包含一个字符串?,第二行包含一个字符串?。


【输出格式】


输出一行,包含一个整数,代表可以通过解密得到原文的?的子串的数量。


【样例输入】


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中所有能成为s的子串

  可以换一种说法

  我们要找的就是t的包含有s串的元素的子串

  但是这个子串只是包含s串还不行

  需要包含的s串的元素有顺序

  就是说从t[0]到t[length_t-1]中

  只要是t[now]和s[0]相等就开始向后面找是否以t[now]开头的子串包含s串的所有元素

  如果找到了

  则标记以t[now]开头的子串的末尾元素记为t[end]

  然后计算t[now]以前的元素个数和t[end]以后的元素个数

  这两个个数的值相乘就是t[now]到t[end]这个子串能够延伸的子串个数(包括它自己)

  O(lenth_t)循环一遍找到所有的t[now]==s[0]的now值

  每个now值都找所有的s串在t串中的顺序值

  如果某个now值没有找全s串的值则返回

  所有能得出值得now的和

  还不是最终的答案

  我们会发现这样所有的now值得出的子串个数会有重复

  这时需要用容斥原理来减去重复的部分

  这样就能得出最后的答案

  但是

  还没完

  虽然答案对了

  但是时间复杂度依然高

  会超时

  所以我们需要做一下优化

  就是弄一个数组来储存所有上一个now的s串元素在t串中的位置

  如果现在的now的位置<s[1]的位置

  则无需再次寻找当前now的s串的元素在t串中位置

  我们可以把上一个now的s串的元素的位置引过来用

  这样减少寻找now的次数

  时间会得到很大的优化

  在时间很少的情况下得出答案;

 

 

来,上代码:

#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

int len_t,len_s,now_s,be_t=-1,s_where[202];

char t_problem[300005],s_before[202];

unsigned long long int ans=0;

bool ok_all=false;

void work_for_ans(int now_t)
{
    if(now_t<s_where[1])
    {
        ans+=(now_t-be_t)*(len_t-s_where[len_s-1]);
        be_t=now_t;
    }
    else
    {
        now_s=1;
        for(int i=now_t+1;i<=len_t;i++)
        {
            if(i==len_t)
            {
                ok_all=true;
                break;
            }
            if(t_problem[i]==s_before[now_s])
            {
                s_where[now_s]=i;
                now_s++;
            }
            if(now_s==len_s) break;
        }
        if(!ok_all)
        {
            ans+=(now_t-be_t)*(len_t-s_where[len_s-1]);
            be_t=now_t;
        }
    }
}

int main()
{
    scanf("%s",t_problem);
    scanf("%s",s_before);
    len_t=strlen(t_problem),len_s=strlen(s_before);
    if(len_s==1)
    {
        for(int i=0 ; i<len_t ;i++)
        {
            if(t_problem[i]==s_before[0])
            {
                ans+=(i-be_t)*(len_t-i);
                be_t=i;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    for(int i=0 ; i<len_t ; i++)
    {
        if(t_problem[i]==s_before[0]) work_for_ans(i);
        if(ok_all) break;
    }
    cout<<ans<<endl;
    return 0;
}

 

posted @ 2016-11-12 14:05  IIIIIIIIIU  阅读(197)  评论(0编辑  收藏  举报