算法二十七:子序列

描述

给定一个字符串,求出该字符串有多少不同的子序列。

子序列:字符串中按顺序抽出一些字符得到的串。比如字符串abcd里,ab、ac、ad、abc、acd都是子序列。

输入

输入一个字符串。

输出

输出不同的子序列的个数除以23333得到的余数。

样例输入

ababc

样例输出

23

样例解释

有这些子序列:

a,b,c,aa,ab,ac,ba,bb,bc,aba,abb,abc,aab,aac,bab,bac,bbc,abab,abac,abbc,aabc,babc,ababc

提示

[令f(i)f(i)为前ii中本质不同的的子序列个数,令pre(i)pre(i)表示字符sisi之前出现的位置,则]

[f(i)={f(i1)+f(i1)+1pre(i)=0f(i1)+f(i1)f(pre(i)1)pre(i)0f(i)={f(i−1)+f(i−1)+1pre(i)=0f(i−1)+f(i−1)−f(pre(i)−1)pre(i)≠0]

[答案等于f(n)f(n).]

一. 伪代码

二. 具体实现(C++)

#include <bits/stdc++.h>
using namespace std;

// ================= 代码实现开始 =================

const int N = 500005, mo = 23333;

int f[N], p[N], last[26];
// 为了减少复制开销,我们直接读入信息到全局变量中
// s:题目所给字符串

char s[N];

// 求出字符串s有多少不同的子序列
// 返回值:s不同子序列的数量,返回值对mo取模

int getAnswer() {
   int n = strlen(s + 1);
   for(int i = 1; i<=n; ++i){
       int a = s[i] - 'a';
       p[i] = last[a];
       last[a] = i;
   }
   f[0] = 0;
   for(int i = 1; i <= n; ++i){
        f[i] = (p[i] == 0)?
                (f[i - 1] + f[i - 1] +1):(f[i - 1]+f[i - 1]-f[p[i]-1]);
        f[i]%=mo;
   }
   return (f[n] + mo) % mo;
}

// ================= 代码实现结束 =================




猜你喜欢

转载自blog.csdn.net/wydyd110/article/details/80909371
今日推荐