您的位置:首页 > 其它

(Kattis - heritage)What Does It Mean?(map+记忆话搜索)(补)

2017-07-30 15:42 357 查看
Time limit1000 m s Memory limit1048576 kB OSLinux

Bob has always been interested in his family history, and above all else his family name’s meaning. Unfortunately for Bob, no one else in his family has ever had any similar interest whatsoever. Because of this the family name seems to have changed at random points in time without any reason that Bob can find.

You have a dictionary of words that may make up part of Bob’s family name, and one or more unique meanings associated with each word. By concatenating one or more of these dictionary words to construct exactly the family name, count the number of different meanings associated with these different constructions.

Input

The first line contains an integer NN and a word WW, indicating the number of words in the dictionary and the family name respectively. The following NN lines contain the dictionary. Each dictionary line starts with the dictionary word followed by an integer representing the number of meanings of the word.

Output

Output the number of possible meanings Bob’s family name can have. As this number can be very large, output it modulo 10000000071000000007.

Limits

1≤N≤10001≤N≤1000

Each word (family name and dictionary) has a length between 11 and 3232 characters (inclusive), and uses only characters a–z.

The number of meanings of a word in the dictionary is at least 11 and at most 1000010000.

Dictionary words are distinct.

Sample Input 1 Sample Output 1

5 heimark

hei 2

mark 2

heim 1

ark 2

heima 1

6

题意:给定一个单词,以及在字典中查阅到的n个单词,和它包含的k种含义,

问,通过这n个单词的拼接,可以是一个或多个,给定的那个单词会出现多少种不同的含义?

训练时当时卡在一道简单题了,看到了这题就觉得自己写出来一定超时,而且很可能WA,看了学长的题解,然后觉得用的真的秒。。

分析:先用map将各个单词和它拥有的含义的个数存起来,令d[i]为i到字符串结尾所包含的不同含义的个数

由乘法和加法原理得,枚举i,d[i]=d[i]+mp[st]*d[i+1],st是由0到i组成的字符串、然后再记忆话搜索

渣渣理解过后写的AC代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<string>
#include<iostream>
using namespace std;
const int mod=1e9+7;
typedef long long LL;
const int N=33;///字符串最长为32
LL num
;
map<string,LL>mp;////因为数量较大,我就直接用LL
string str;
int dfs(int cnt)
{
LL& ret=num[cnt];///此处用了 “引用”
if(cnt==str.length())///找到了匹配的字符串的末尾
return 1;
if(ret!=-1) return ret;///已经搜过了,就不用再搜索了,直接返回之前的
LL sum=0;
string st("");
for(int i=cnt;i<str.length();i++)
{
st+=str[i];
if(mp.find(st)!=mp.end())////如果st这个字符串存在mp中,继续搜索
{
sum=(sum+mp[st]*dfs(i+1))%mod;
}
}
return ret=sum;///返回最终的结果
}
int main()
{
int n;
while(cin>>n>>str)
{
memset(num,-1,sizeof(num));///初始化,num[i]为-1表示没有搜过
int m;
mp.clear();///清空
string sstri;
for(int i=0;i<n;i++)
{
cin>>sstri>>m;
mp[sstri]=m;///将给的单词的含义值存起来
}
cout<<dfs(0)<<endl;
}
return 0;
}


个人总结:这个题只给了1s,然后是一个要求数量的问题,这两天回顾了一下DP,其中一个很重要的就是记忆化,这样会节省大量时间字符串匹配,之前好像也有一个字符串前缀匹配,也用到了map,感觉map对于这类问题用起来,屡试不爽。。 代码也比较简短,记一下!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  map 记忆话搜索