C-Crossword Validation(字典树算法)

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值