找子串数(牛客练习赛23,i++与++i)

托米没有完成上一个任务,准备施展黑魔法推倒 1317

黑魔法咒语被描述为一个 长为 n 的,仅包含小写英文字母 'a'...'i' 的字符串,在托米所在的星球,魔法造成的每次有效伤害都是来自他的一个子序列,对于每一个 'a'... 'i' 的排列(共 9! 种),若作为咒语的子序列出现, 就会造成 1 的伤害

而咒语的总伤害为所有 'a'... 'i' 的排列造成的伤害值之和,托米能打出多少点的伤害,是否能击败 1317 呢?

输入描述:

一行输入一个字符串 s

输出描述:

一行输出一个数,表示伤害值

示例1

输入

aabcdefghi

输出

1

备注:

|s| ≤  3000

题意:给出一个大串,要求在大串中找a~i的全排列个数。大串中重复的全排列不计入。(限时1s)

历程/思路:本来是一道很水的题,用STL中的全排列函数就能卡过,时间大概在800,900ms左右,或者处理一下大串中字母的位置就能达到10ms左右的样子,但是中间出了很多毛病。最开始是用的string+全排列,过百分之80,超时。然后有大佬告诉我这道题暴力是能过的,苦苦寻找超时的原因,最后学长认为是++i与i++的问题,还查阅了相关的资料还真的神tm有点问题(i++与++i的效率问题:https://blog.csdn.net/linuxdriverdeveloper/article/details/8767563)然后第二天高高兴兴的复盘,结果。。。为毛i++能过呀,完全不是这个东西的问题啊......算了,也是涨见识了,以后要改改++的习惯了。

不处理全排列暴力做法(900ms左右):

#include<bits/stdc++.h>
using namespace std;
int main()
{
  char a[10]="abcdefghi";
  char b[5000];
  int sum=0;
  cin>>b;
  do{
    int t=0,i=0;
    while(t<9&&b[i])
     {
        if(a[t]==b[i])
        {
            ++t;
            ++i;
        }
        else{
            ++i;
        }
     }if(t==9)
        {
            sum++;
        }
  }while(next_permutation(a,a+9));
   cout<<sum;
}

处理后再全排列做法(9ms):

#include<bits/stdc++.h>
using namespace std;
int num[10];
int dp[3010][10];
int main()
{
    string s;
    cin>>s;
    s=' '+s;
    for(int i=s.size()-1;i>=0;i--)
    {
        for(int j=0;j<=9;j++) dp[i][j]=num[j];//初始化操作 
        if(i!=0)num[s[i]-'a']=i;//num存字母在原串中的位置 
    }
    char v[10]={"abcdefghi"};
    int ans=0;
    do{
        int flag=0;
        for(int i=0;i<9;i++)
        {
            flag=dp[flag][v[i]-'a'];//判断顺序是否符合 
            if(flag==0) 
			{
			   ans--;
			   break;
			}
        }
        ans++;
    }while(next_permutation(v,v+9));
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/pleasantly1/article/details/81257222