SDUT 2023 summer team contest(for 22) - 4 - Virtual Judge (vjudge.net)
题意:给n*n的矩阵,矩阵由小写字母和#组成,和m个字典单词及其对应分数,矩阵中单词向下向右遍历,直到遇到#则构成一个单词,查询该单词在字典中对应分数并累加,如果未查询到则无效
思路:第一种:将m个单词插入字典树同时保存对应分数,查询矩阵中单词分数并检验是否有效
第二种:预处理出m个单词的map值,再直接查询矩阵单词的分数
(下面给出字典树的做法)
注意:1,字典树tr[N][28]的N因为插入单词是m,也就是4e6级别
2,同时因为内存较大,long long需要换成int,只long long 必要变量(否则超内存)
3,初始化tr数组和ww数组时,每次都只初始化上个样例的节点数,否则多组样例输入memset整个size很可能会超时
#include <bits/stdc++.h>
#define PI 3.14159265358979323
//#define int long long
#define Close ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
const int N=4e6+10;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
//typedef pair<int,int> pii;
/*vector<pii> q(N);
vector<int> g[N];
set<int> s1;
map<string,vector<string>> mpp;
unordered_map<int,int> ump;
map<pair<double,double>,int> mmp;*/
int n,m,idx;
char a[1005][1005];
int tr[N][28],ww[N],len;
void add(string s,int w)
{
int p=0,len=s.size();
for(int i=0;i<len;i++)
{
int u=s[i]-'a';
if(!tr[p][u]) tr[p][u]=++idx;
p=tr[p][u];
}
ww[p]=w;
}
int find(string s)
{
int p=0,len=s.size();
for(int i=0;i<len;i++)
{
int u=s[i]-'a';
if(tr[p][u]) p=tr[p][u];
else return 0;
}
return ww[p];
}
void solve()
{
for(int i=0;i<=idx;i++)
{
ww[i]=0;
for(int j=0;j<26;j++)
tr[i][j]=0;
}
idx=0;
int w;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
cin>>a[i][j];
}
}
while(m--)
{
string s;
cin>>s>>w;
add(s,w);
}
long long res=0;
for(int i=1;i<=n;i++)
{
string ss,st;
for(int j=1;j<=n;j++)
{
if(a[i][j]!='#') ss+=a[i][j];
else
{
//res+=find(ss);
if(find(ss)==0&&ss!="")
{
cout<<-1<<endl;
return;
}
else res+=find(ss);
ss="";
}
if(a[j][i]!='#') st+=a[j][i];
else
{
//res+=find(st);
if(find(st)==0&&st!="")
{
cout<<-1<<endl;
return;
}
else res+=find(st);
st="";
}
}
if(find(ss)==0&&ss!="")
{
cout<<-1<<endl;
return;
}
else res+=find(ss);
if(find(st)==0&&st!="")
{
cout<<-1<<endl;
return;
}
else res+=find(st);
}
cout<<res<<endl;
}
signed main()
{
Close
int T;
//T=1;
cin>>T;
while(T--)
{
solve();
}
return 0;
}