Luogu 统计单词个数
来源:互联网 发布:jre1.8 源码下载 编辑:程序博客网 时间:2024/05/18 01:53
题目描述
给出一个长度不超过200的由小写英文字母组成的字母串(该字串以每行20个字母的方式输入,且保证每行一定为20个)。
要求将此字母串分成k份(2<=k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠)。
当选用一个单词之后,其第一个字母不能再用。例如字符串 this 中可包含 this 和 is,选用 this 之后就不能包含 th。
单词在给出的一个不超过6个单词的字典中。
要求输出最大的个数。
输入输出格式
输入格式:
每组的第一行有二个正整数(p,k)
p表示字串的行数;
k表示分为k个部分。
接下来的p行,每行均有20个字符。
再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)
接下来的s行,每行均有一个单词。
输出格式:
一个整数,分别对应每组测试数据的相应结果。
输入输出样例
输入样例#1:
1 3
thisisabookyouareaoh
4
is
a
ok
sab
输出样例#1:
7
说明
this/isabookyoua/reaoh
这道题想了很久,最终想出来了一个非搜索非DP的做法,而且速度还很快。
❀ 先将字典按单词长度从小到大排序,因为如果两个单词的起始位置一样,优先选择长度短的单词。
❀ 用结构体 a 来记录每个位置被多少个单词覆盖,a[i].v 表示字串里 i 这个位置被 v 个单词覆盖。
❀ 忽略 k 直接从字串里查一共有几个单词,记总数为 tot,找到一个单词就把这个单词覆盖位置的 v++。
❀ 注意每个单词最后一个字母的 v 值不需要累加,因为截断 i 这个位置指的是在字母 i 后面截断,而在最后一个字母后面截断对整个单词无影响。
❀ 将 a 按 v 值由小到大进行排序,这样被单词覆盖少的位置就排到了前面,如果要截断的话,优先截断这些位置;由于顺序会被打乱,所以在排序前用 a[i].t 记录原来的位置。
❀ 这样就可以直接从头开始用 tot 减去 k 个 a[i].v 了吗?还需要注意一点的是,截断一个位置后,覆盖这个位置的单词消失,因此要把这个消失的单词覆盖的位置都减一,防止后面重复减。
思路是正确的,程序应该还有一些不完善的地方,因为本人比较懒啦,少写了一些条件,不过我不想改它了,至少它在各大OJ上AC了。
我自己就可以找出一些反例让它爆零。所以不要copy我的程序,按着上面的思路来做吧。
下面是一个假的程序(◑▽◐)
//统计单词个数#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,k,p,tot,l;struct tWord{ char s[210]; int left[210],l,n;}d[10];struct tWide{ int v,t;}a[210];char st[210];bool cmp(tWord x,tWord y){ return x.l<y.l;}bool cmp2(tWide x,tWide y){ return x.v<y.v;}void start(){ char ch[210]={}; bool head[210]={}; char *h; for(int i=0;i<p;++i) { strcpy(ch,st); h=strstr(ch,d[i].s); while(h!=NULL) { if(head[h-ch]==0) { ++tot; d[i].left[d[i].n++]=h-ch; head[h-ch]=1; for(int j=h-ch;j<h-ch+d[i].l-1;++j) ++a[j].v; } ch[h-ch]='*'; h=strstr(ch,d[i].s); } }}void cut(){ for(int i=0;i<l;++i) a[i].t=i; a[0].v=0x7fffffff; sort(a,a+l,cmp2); for(int i=0;i<k;++i) { tot-=a[i].v; for(int j=0;j<p;++j) for(int k=0;k<d[j].n;++k) if(d[j].left[k]==a[i].t) for(int m=a[i].t;m<a[i].t+d[j].l;++m) --a[m].v; }}int main(){ scanf("%d%d",&n,&k); --k; for(int i=0;i<n;++i) { char ch[25]; scanf("%s",ch); strcat(st,ch); l+=20; } scanf("%d",&p); for(int i=0;i<p;++i) { scanf("%s",d[i].s); d[i].l=strlen(d[i].s); } sort(d,d+p,cmp); start(); cut(); printf("%d\n",tot); return 0;}
- Luogu 统计单词个数
- [洛谷luogu] [NOIP2001T3]统计单词个数 (DP)
- vc 统计单词个数
- 统计单词个数
- 统计单词个数
- 统计单词个数
- 统计单词个数
- 统计单词个数
- 统计单词个数
- 状态机统计单词个数
- wikioi1040 统计单词个数
- C统计单词个数
- 统计不同单词个数
- 统计单词个数
- acm-统计单词个数
- 17.2统计单词个数
- 统计单词个数
- DP-统计单词个数
- FTPrep, 34 Search for a range
- java使用neo4j图数据库—centos7.1
- error:Your display is too small to run Menuconfig!
- oppo系列手机Root、破解联通4g、解决联通网络不稳定、无信号等
- UVA 11134 Fabled Rooks
- Luogu 统计单词个数
- jQuery插件开发(一)
- Object的wait()、notify、notify 侵立删
- SIM800C二次开发
- 相机硬触发的接线方法
- Kmeans、Kmeans++和KNN算法比较
- ICPC XIV NEERC Western Subregional Contest I题
- luoguP1063 能量项链
- 数据库连接池dbcp配置