禁止字符串 字符串上的动态规划

// 禁止字符串 字符串上的动态规划
// 挑战程序设计第二版 page 368
// 考虑只由'A','G','C','T'四种字符组成的DNF字符串
// 给定一个长度为k的字符串S,计算长度恰好为n的且
// 不包含S的字符串的个数输入结果对10009取膜
// 1<=k<=100
// 1<=n<=10000
//
// 这道题想动态规划,肯定是n*k的算法,即10的七次方以内
// 的复杂度
//
// 但是,之后就卡住了。。。
//
// 仔细研习了书上的思路,发现状态定义的有点巧妙
// dp[i][j] 表示前i个字符最后面j个字符与S的前j个字符匹配的
// 合法的字符串的数目
// 则
// dp[i+1][j] = sigma(dp[i][x])(0<=x<k)
//
// 书上的预处理十分巧妙 直接预处理出从某个状态后面添加一个字符
// 所达到的状态的表
//
// 这个算法让我懂了挺多的,思路开阔了很多
// 继续练吧。。。。
//

#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
int n,k;
string S;

const char *agct = "AGCT";

const int maxn = 1009;
int dp[maxn][108];
int next[maxn][5];
const int MOD = 10009;
void init(){
	memset(dp,0,sizeof(dp));
	dp[0][0] = 1;
}

void solve(){
	for (int i=0;i<k;i++){
		for (int j=0;j<4;j++){
			// 取S的前i个元素并在后面添加一个元素
			string s = S.substr(0,i) + agct[j];
			//反复删除s的第一个元素,直到s成为S的前缀
			while(S.substr(0,s.length())!=s){
				s = s.substr(1);
			}
			next[i][j] = s.length();
		}
	}

	for (int i=0;i<n;i++){
		for (int x=0;x<k;x++){
			for (int j=0;j<4;j++){
				int t = next[x][j];
				if (t==k)	continue;
				dp[i+1][t] = (dp[i+1][t] + dp[i][x]) % MOD;
			}
		}
	}
	int ans = 0;
	for (int i=0;i<k;i++)
		ans = (ans + dp[n][i]) % MOD;
	cout << ans << endl;
}

int main(){
	while(cin>>n>>k>>S){
		init();
		solve();
	}
}

时间: 2024-08-26 04:56:16

禁止字符串 字符串上的动态规划的相关文章

Go 数字转字符串,字符串转数字, 枚举

数字转字符串,字符串转数字 package main import ( "fmt" "strconv" ) func main() { // 80 转换成 "80" //number := 80 // //number_int :=strconv.Itoa(number) // //fmt.Println(number_int) //fmt.Printf("%T", number_int) // 如果不用这种的,可能转出来的不

《Python CookBook2》 第一章 文本 - 测试一个对象是否是类字符串 &amp;&amp; 字符串对齐

测试一个对象是否是类字符串 任务 有时候需要测试一个对象,尤其是当你在写一个函数或者方法的时候,经常需要测试传入的参数是否是一个字符串. 解决方案 利用内建的isinstance 和basestring 来简单快速地查询某个对象是否是字符串或者是Unicode 对象方法,如下: 代码: >>> def isAString(aaa): return isinstance(aaa,basestring) 运行结果: >>> isAString('aaa') True 字符串

ACM:DAG上的动态规划------硬币问题

ExecutorService 建立多线程线程池的步骤: 线程池的作用: 线程池作用就是限制系统中执行线程的数量. 根据系统的环境情况,可以自动或手动设置线程数量,达到运行的最佳效果:少了浪费了系统资源,多了造成系统拥挤效率不高.用线程池控制线程数量,其他线程排队等候.一个任务执行完毕,再从队列的中取最前面的任务开始执行.若队列中没有等待进程,线程池的这一资源处于等待.当一个新任务需要运行时,如果线程池中有等待的工作线程,就可以开始运行了:否则进入等待队列. 为什么要用线程池: 1.减少了创建和

UVa 103 Stacking Boxes --- DAG上的动态规划

UVa 103 题目大意:给定n个箱子,每个箱子有m个维度, 一个箱子可以嵌套在另一个箱子中当且仅当该箱子的所有的维度大小全部小于另一个箱子的相应维度, (注意箱子可以旋转,即箱子维度可以互换),求最多能套几个箱子. 第一行输入为n,m,之后是n行m维的箱子 解题思路:嵌套关系是二元关系,因此这题即在DAG上做动态规划, 只不过将二维的判断改成了n维,其他不变. 详细看考:DAG上的动态规划之嵌套矩形  (ps:这题可以理解成嵌套m边形) /* UVa 103 Stacking Boxes --

C# 支持两种形式的字符串:规则字符串和逐字字符串(@字符串)

规则字符串由包含在双引号中的零个或多个字符组成(如 "hello"),并且可以包含简单转义序列(如表示制表符的 \t).十六进制转义序列和 Unicode 转义序列. 逐字字符串由 @ 字符后跟开始的双引号字符.零个或多个字符以及结束的双引号字符组成.一个简单的示例就是 @"hello".在逐字字符串中,分隔符之间的字符逐字解释,唯一的例外是"引号转义序列".具体说来,在逐字字符串中不处理简单转义序列以及十六进制 和 Unicode 转义序列.逐

DP入门(2)——DAG上的动态规划

有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 一.DAG模型 [嵌套矩形问题] 问题:有n个矩形,每个矩形可以用两个整数a.b描述,表示它的长和宽.矩形X(a , b)可以嵌套在矩形Y(c , d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩形X旋转90°).例如(1,5)可以嵌套在(6, 2)内,但不能嵌套在(3, 4)内.你的任务是选出尽可能多的矩形排

phpmyadmin导入数据库显示 此服务器禁止了文件上传

centos 服务器安装好phpmyadmin 在文件上传的时候提示  此服务器禁止了文件上传 解决的方法: 1:首先登陆 phpmyadmin 2:进入界面 点击 用户账户(版本不一样 大概就是管理账号的位置) 3:查找自己的账号 修改 host name (localhost) 为 (%) 重启服务器 再去远程访问phpmyadmin 提示可以导入数据库文件了,解决了这个错误

嵌套矩形——DAG上的动态规划

有向无环图(DAG,Directed Acyclic Graph)上的动态规划是学习动态规划的基础.很多问题都可以转化为DAG上的最长路.最短路或路径计数问题. 题目描述: 有n个矩形,每个矩形可以用两个整数a,b描述,表示它的长和宽.矩形X(a,b)可以嵌套在矩形Y(c,d)中当且仅当a<c,b<d,或者b<c,a<d(相当于把矩形X旋转90°).例如(1,5)可以嵌套在(6,2)内,但不能嵌套在(3,4)内.你的任务是选出尽可能多的矩形排成一行.使得除了最后一个之外,每个矩形都

Monkey and Banana(DAG上的动态规划问题)

Monkey and Banana Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8122    Accepted Submission(s): 4194 Problem Description A group of researchers are designing an experiment to test the IQ of a