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

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

而咒语的总伤害为所有 ‘a’… ‘i’ 的排列造成的伤害值之和,托米能打出多少点的伤害,是否能击败 1317 呢?
提交的代码
提交时间:2018-07-28 09:40:07 语言:C++ 代码长度:490 运行时间: 895 ms 占用内存:504K
运行结果:答案正确

暴力

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
//#define int long long
char s[5000];
signed main()
{
    int ans = 0;
    cin>>s;
    char a[10]="abcdefghi";
    do{

       int t =0 ;
       int i = 0;
       while(t<9&&s[i])
       {
            if(a[t]==s[i])
            {
                t++;
                i++;
            }
            else i++;
       }
       if(t==9)
       ans++;

    }while(next_permutation(a,a+9));
    cout<<ans<<endl;
    //return 0;
}

二分

#include<stdio.h>
#include<string.h>
#include<vector>
#include<stdlib.h>
#include<algorithm>
using namespace std;
char s[3005];
vector<int>v[10];
char a[]={'a','b','c','d','e','f','g','h','i'};
int main(){
    scanf(" %s",s);
    int len=strlen(s);
    for(int i=0;i<len;i++){
        v[s[i]-'a'].push_back(i);
    }
    for(int i=0;i<9;i++){
        v[i].push_back(len);
    }
    int ans=0;
    do{
        int leap=0,h=0;
        for(int i=0;i<9;i++){
            h=*lower_bound(v[a[i]-'a'].begin(),v[a[i]-'a'].end(),h);
            if(h==len){
                leap=1;
                break;
            }
        }
        if(!leap)
            ans++;
    }while(next_permutation(a,a+9));
    printf("%d\n",ans);
    return 0;
}

预处理出下一个位置

#include <bits/stdc++.h>

using namespace std;
const int maxn = 3000 + 7;
char s[maxn], p[10];
int nx[maxn][30], first[30];
int main(){
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    for(int i = 0; i < 9; i++) p[i + 1] = 'a' + i;
    for(int i = 0; i <= n; i++){
        for(int j = i + 1; j <= n; j++){
            if(nx[i][s[j] - 'a'] == 0) nx[i][s[j] - 'a'] = j;
        }
    }
    int ans = 0;
    do{
        bool flag = true;
        int now = 0;
        for(int i = 1; i <= 9; i++){
            if(nx[now][p[i] - 'a']) now = nx[now][p[i] - 'a'];
            else{
                flag = false;
                break;
            }
        }
        if(flag) ans++;
    }while(next_permutation(p + 1, p + 9 + 1));
    printf("%d\n", ans);
    return 0;
}

更快的预处理:

#include <bits/stdc++.h>

using namespace std;
const int maxn = 3000 + 7;
char s[maxn], p[10];
int nx[maxn][30], first[30], pos[30];
int main(){
    scanf("%s", s + 1);
    int n = strlen(s + 1);
    for(int i = 0; i < 9; i++) p[i + 1] = 'a' + i;
    for(int i = n; i >= 0; i--){
        for(int j = 0; j < 9; j++) nx[i][j] = pos[j];
        if(i) pos[s[i] - 'a'] = i;
    }
    int ans = 0;
    do{
        bool flag = true;
        int now = 0;
        for(int i = 1; i <= 9; i++){
            if(nx[now][p[i] - 'a']) now = nx[now][p[i] - 'a'];
            else{
                flag = false;
                break;
            }
        }
        if(flag) ans++;
    }while(next_permutation(p + 1, p + 9 + 1));
    printf("%d\n", ans);
    return 0;
}