Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression

题意:

给你一个字符串,让你压缩,问压缩后最小的长度是多少。

压缩的形式为x(...)x(...)  x表示(...)这个出现的次数。

题解:

考虑dp[i]表示前i个字符压缩后的最小长度。

转移方程解释看代码,这里要用到kmp来找最小的循环节。

当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式。

这里我用的kmp找的循环节。复杂度严格n2

 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;++i)
 3 using namespace std;
 4
 5 void kmp_pre(char *x,int m,int *nxt){
 6     int i,j;
 7     j=nxt[0]=-1,i=0;
 8     while(i<m){
 9         while(-1!=j&&x[i]!=x[j])j=nxt[j];
10         nxt[++i]=++j;
11     }
12 }
13 const int N=10000;
14 int len,nxt[N],dp[N],cnt[N];
15 char s[N],buf[20],str[N];
16
17 int main(){
18     scanf("%s",s);
19     len=strlen(s);
20     F(i,1,len)cnt[i]=sprintf(buf,"%d",i),dp[i]=i+1;
21     F(i,0,len-1)
22     {
23         strcpy(str,s+i);
24         kmp_pre(str,len-i,nxt);
25         for(int j=1;i+j<=len;j++)//枚举长度
26         {
27             int L=j-nxt[j];//以j结尾的子串的最小循环节
28             if(j%L==0)//如果这个子串的长度恰好能整除最小循环节,那么可以按照最小循环节压缩。
29             {
30                 dp[i+j]=min(dp[i+j],dp[i]+L+cnt[j/L]);
31             }else dp[i+j]=min(dp[i+j],dp[i]+j+cnt[1]);
32         }
33     }
34     printf("%d\n",dp[len]);
35     return 0;
36 }

时间: 2024-10-10 22:54:50

Educational Codeforces Round 25 F. String Compression(kmp+dp)的相关文章

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Educational Codeforces Round 24 F. Level Generation(三分)

题目链接:Educational Codeforces Round 24 F. Level Generation 题意: 给你n个点,让你构造ans条边,使得这ans条边中至少有一半是桥. 让你求ans的最大值. 题解: 首先我们将每一个点按顺序连起来,那么可以构成n-1个桥. 然后我们可以把其中的x个点拿出来连边,这些边都不是桥. x个点最多能连x*(x-1)条边,然后剩下的n-x个点连的边将会构成桥. 然后就可以构造一个函数关系,详见check函数,然后三分一下就行了. 1 #include

Educational Codeforces Round 21 F. Card Game(网络流之最大点权独立集)

题目链接:Educational Codeforces Round 21 F. Card Game 题意: 有n个卡片,每个卡片有三个值:p,c,l; 现在让你找一个最小的L,使得满足选出来的卡片l<=L,并且所有卡片的p的和不小于k. 选择卡片时有限制,任意两张卡片的c之和不能为质数. 题解: 和hdu 1565 方格取数(2)一样,都是求最大点权独立集. 不难看出来,这题再多一个二分. 注意的是在构造二部图的时候,按照c值的奇偶性构造. 当c==1时要单独处理,因为如果有多个c==1的卡片,

Educational Codeforces Round 25 G. Tree Queries

题目链接:Educational Codeforces Round 25 G. Tree Queries 题意: 给你一棵树,一开始所有的点全是黑色,有两种操作. 1 x 将x这个点变为黑色,保证第一个操作是这个. 2 x 询问x到任意黑色的点的简单路径上的最小节点编号. 题解: 首先将一个变为黑色的点当成树根,然后dfs一下,预处理出所有点的答案. 然后开一个变量记录一下当前变黑的点的答案cur=min(cur,dp[x]). 每次询问的时候答案就是min(cur,dp[x]). 如果觉得很神

Educational Codeforces Round 76 F 折半枚举

Educational Codeforces Round 76 F 折半枚举 https://codeforces.com/contest/1257/problem/F 题意: 数组a,找到一个x使得a中每一个元素异或x后"二进制中1的个数"相同. 数组长度100,数字大小2^30. 思路: 折半枚举答案X,如分为X前15位和后15位.之后我们再枚举期望的"相同个数"是多少,通过hash看看能不能满足就好了. 代码: #include <bits/stdc++

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

Educational Codeforces Round 25 D - Suitable Replacement(贪心)

题目大意:给你字符串s,和t,字符串s中的'?'可以用字符串t中的字符代替,要求使得最后得到的字符串s(可以将s中的字符位置两两交换,任意位置任意次数)中含有的子串t最多. 解题思路: 因为知道s中的字符位置可以交换无数次,所以只要s中含有可以组成t的字符就一定可以出现子串t.所以就是要令t中的字符数量尽量平均地分布在s中. 代码: 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 int str[30

Educational Codeforces Round 14 - F (codeforces 691F)

题目链接:http://codeforces.com/problemset/problem/691/F 题目大意:给定n个数,再给m个询问,每个询问给一个p,求n个数中有多少对数的乘积≥p 数据范围:2≤n≤10^6, 1≤ai≤3*10^6,1≤m≤10^6, 1≤p≤3*10^6 解题思路:比赛的时候比较naive的思路是把n中的数字排序去了重之后,对于每个p,最多枚举√p步,就能得到答案.而这个naive的思路是O(p√p)的,结果T了. 后来百思不得其解,去看了官方的解答.感觉是一种很有

Educational Codeforces Round 25

A题 分析:遇到1就统计有几个连续的,遇到0若连续的多于一个就输出后面的0 1 #include "iostream" 2 #include "cstdio" 3 #include "cstring" 4 #include "string" 5 #include "vector" 6 using namespace std; 7 int n; 8 string s; 9 int main() 10 { 11