首页 > 试题广场 >

手机号查询

[编程题]手机号查询
  • 热度指数:1699 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
信服君接到一项任务需要制作一个手机号码查询系统,输入连续的数字后,需要显示所有包含该连续数字的手机号。为了验证算法,信服君目前只需输出手机号的个数即可。


输入描述:
首行输入两个整数N,M(1<=N<=15000,1<=M<=100000),之后是N行输入,表示有N个手机号码,每个手机号码由11位首位不为零的连续数字组成,接着是M行查询,每行由连续的数字组成,长度为L(1<=L<=11)。


输出描述:
每个请求输出包含查询数字串的不同的手机号共有多少个。
示例1

输入

3 2
15623651459
18956036508
18625690367
333
036

输出

0
2

备注:
输入手机号可能有冗余
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e3+5;
typedef long long ll;

unordered_map<string,bool>vis;
unordered_map<string,int>cnt;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
	int n,m;
	cin>>n>>m;
	string s;
	while(n--){
		cin>>s;
		if(vis.count(s)) continue;
		vis[s]=true;
		set<string>st;
		for(int i=0;i<11;i++){
			for(int j=i;j<11;j++){
				st.insert(s.substr(i,j-i+1));
			}
		}
		for(auto t:st) cnt[t]++;
	}
	while(m--){
		cin>>s;
		cout<<cnt[s]<<'\n';
	}
    return 0;
}
发表于 2020-05-14 19:04:17 回复(0)
//map去重+双hash+散列表,内存差点炸了,精打细算一下刚刚好
/*author: revolIA*/
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<unsigned int,unsigned int> pll;
inline pll operator - (pll a,pll b){return make_pair((a.first -  b.first),(a.second - b.second));}
inline pll operator * (pll a,pll b){return make_pair((a.first *  b.first),(a.second * b.second));}
inline pll operator + (pll a,pll b){return make_pair((a.first +  b.first),(a.second + b.second));}
inline pll operator + (pll a,int b){return make_pair((a.first +  b      ),(a.second + b       ));}
const int maxn = 1e6+7;
const pll p = {23,2333};
int n,m;
char opt[20];
int head[maxn],Next[maxn],cnt;
pair<pll,int> val[maxn];
int Find(pll x){
    int pos = (int)(x.first*x.second%maxn);
    for(int i=head[pos];i;i=Next[i])if(x == val[i].first)
        return i;
    return -1;
}
void Insert(pll x){
    int pos = Find(x);
    if(~pos){
        val[pos].second++;
        return;
    }
    pos = (int)(x.first*x.second%maxn);
    val[++cnt] = {x,1};
    Next[cnt] = head[pos];
    head[pos] = cnt;
}
map<pll,bool> vis,tvis;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%s",opt+1);
        pll ans = {0,0};
        for(int i=1;i<=11;i++)ans = ans*p+opt[i];
        if(tvis.count(ans))
            continue;
        tvis[ans] = 1;
        vis.clear();
        for(int l=1;l<=11;l++){
            ans = {0,0};
            for(int r=l;r<=11;r++){
                ans = ans*p+opt[r];
                if(!vis.count(ans)){
                    ++vis[ans];
                    Insert(ans);
                }
            }
        }
    }
    for(int i=1;i<=m;i++){
        scanf("%s",opt+1);
        pll tmp = {0,0};
        for(int j=1;opt[j];j++){
            tmp = tmp*p+opt[j];
        }
        int pos = Find(tmp);
        printf("%d\n",pos!=-1?val[pos].second:0);
    }
    return 0;
}

发表于 2020-05-01 11:13:42 回复(0)
bool isphonenum(string str)
{
    if (str.length() != 11) //长度必须11位
        return false;
    if (str[0] == 0)  //首位不能为0
        return false;
    for (int i = 0; i < 11; i++)
    {
        if (!isdigit(str[i]))  //每一位都为数字
            return false;
    }
    return true;
}

int main()
{
    int N, M;
    cin >> N >> M;
    vector<string> phonenum;
    vector<int> count;
    while (N--)
    {
        string str;
        cin >> str;
        if (isphonenum(str))
        {
            phonenum.push_back(str);
        }
    }
    while (M--)
    {
        int temp = 0;
        string str;
        cin >> str;
        if (str == "")
            continue;
        for (int i = 0; i < phonenum.size(); i++)
        {
            if (phonenum[i].find(str) != string::npos)
                temp++;
        }
        count.push_back(temp);
    }
    for (int i = 0; i < count.size(); i++)
    {
        cout << count[i] << endl;
    }

return 0;
}

发表于 2022-03-18 17:09:56 回复(0)
通过90%,不知道是不是因为手机号码有冗余的原因,话说这个有冗余是什么意思?
#include<bits/stdc++.h>
using namespace std;
int main(){
    int i,j,n,q;
    unordered_map<string,int>m;
    scanf("%d%d",&n,&q);
    while(n--){
        string s;
        cin>>s;
        unordered_set<string>c;
        for(i=0;i<11;++i){
            string t;
            for(j=i;j<11;++j){
                t+=s[j];
                c.insert(t);
            }
        }
        for(auto p:c)m[p]++;
    }
    while(q--){
        string s;
        cin>>s;
        cout<<m[s]<<endl;
    }
    return 0;
}


发表于 2020-05-12 20:00:04 回复(1)
#include<bits/stdc++.h>
using namespace std;
int n,q;
unordered_map<string, long long>m;
map<string,int>check;
set<string>se;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>q;
    while(n--)
    {
        string str;
        cin>>str;
        se.insert(str);
    }
    for(auto it : se)
    {
        string str = it;
        check.clear();
        for(int i=0;i<str.size();i++)
        {
            for(int j=1;j<=11;j++)
            {
                if(i+j <= str.size())
                {
                    string tmp = str.substr(i,j);
                    if(check[tmp] == 0)
                    {
                        check[tmp] = 1;
                        m[tmp]+=1;
                    }
                    else continue;
                }
            }
        }
    }
    while(q--)
    {
        int cnt = 0;
        string s;
        cin>>s;
        cnt = m[s];
        cout<<cnt<<endl;
    }
    return 0;
}
解题思路:查询次数配上手机号码个数太多,不能一个一个号码进行查询。而查询的字符串固定,因此我们需要提前处理一下可能被查询到的字符串。手机号只有11位,查询的字符串长度为1-11,因此我们可以将每个手机号的子串进行枚举,复杂度为O(n*11*11),每次枚举子串开始起点和子串长度,不过需要使用map进行去重,还有一个点,使用unordered_map来进行最后的查询,会降低时间复杂度,map查询可能为O(logn)而unordered_map为O(1)
发表于 2024-08-16 16:53:20 回复(0)
因为手机号长度只有11位所以可以把他所有的子集求出来 时间复杂度 为15000 * 11 * 11 * 11
#include <bits/stdc++.h>
using namespace std;

int n, m;

unordered_set<string> objs;
unordered_map<string, int> cnt;

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m;
    for (int i = 0; i < n; i ++) {
        string s;
        cin >> s;
        objs.emplace(s);
    }
    
    for (auto &i : objs) {
    	if (i.size() != 11) 
			continue;
		unordered_map<string, bool> st;
    	for (int idx = 0; idx < 11; idx ++) {
    		for (int k = 1; k <= 11 - idx; k ++) {
    			string tmp = i.substr(idx, k);
    			if (st[tmp]) continue;
    			st[tmp] = 1;
    			cnt[tmp] ++;
			}
    			
		}
	}
    
    for (int i = 0; i < m; i ++) {
        int res = 0;
        string s;
        cin >> s;
        cout << cnt[s] << "\n";
    }
}


发表于 2022-08-31 23:52:33 回复(0)
AC90%,都这样了还运行超时,救救我
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt(), M = scanner.nextInt();
//        String[] checks = new String[N];
        Map<String, Integer> hashMap = new HashMap<>();
        Set<String> strings = new HashSet<>();
        scanner.nextLine();
        for (int i = 0; i < N; i++) {
            String s = scanner.nextLine();
            if (s.length() == 11 && strings.add(s)) {
                Set<String> checks = new HashSet<>();
                for (int j = 0; j < 11; j++) {
                    for (int k = j + 1; k <= 11; k++) {
                        String s1=s.substring(j, k);
                        if (checks.add(s1)){
                            hashMap.put(s1, hashMap.getOrDefault(s1, 0) + 1);
                        }
                    }
                }
            }
        }
        for (int i = 0; i < M; i++) {
            String query = scanner.nextLine();
            System.out.println(hashMap.getOrDefault(query, 0));
        }
    }
}


发表于 2021-09-16 21:05:28 回复(0)
#include <iostream>
#include <string>
using namespace std;
bool func(string number, string phoneNumber){
    for(int i = 0; i < phoneNumber.length();i++){
        if(number[0]==phoneNumber[i] && (i+number.length())<phoneNumber.length()){
            int j;
            for(j = 1; j <number.length();j++){
                if(number[j]!=phoneNumber[i+j]){
                    break;
                }
            }
            if(j==number.length()){return true;}
        }
    }
    return false;
};
 
int main()
{
    string phoneNumber[15000]={},number[10000]={};
    int N, M;
    cin >> N >> M;
    //输入
    for(int i = 0; i<N; i++){
        cin >> phoneNumber[i];
    }
    for(int i = 0;i<M;i++){
        cin >> number[i];
    }
    //统计
    for(int i = 0; i<M; i++){
        int cnt = 0;
        for(int j = 0;j<N;j++){
            if(func(number[i],phoneNumber[j])){
                cnt++;
            }
        }
        cout << cnt <<endl;
    }
    return 0;

我在自己的环境上测试本样例通过了,有无大佬看看我哪出问题了(用的最简单粗暴的逐项对比法)
发表于 2021-06-22 19:48:50 回复(0)
写一下我的吧,感觉low爆了,在我的VS2019上可以运行,但是提交有错误,不知道为啥。。。
#include <iostream>
#include <string>
#include <array>
#include <vector>
using namespace std;

void function()
{
	int n_str, n_num;
	cin >> n_num>>n_str;        // n_num个号码 n_str个子串
	vector<int> count(n_str,0);
	array<string, 10> arr_str, arr_num;  // 子串   号码
	string s;
	for (int i = 0; i < n_num; i++)
	{	
		cin >> s;
		arr_num[i] = s;
	}
	for (int i = 0; i < n_str; i++)
	{
		cin >> s;
		arr_str[i] = s;
	}
	for (int i = 0; i < n_str; i++)
	{
		for (int j = 0; j < arr_num.size(); j++)
		{
			if (arr_num[j].find(arr_str[i]) != std::string::npos)
				count[i]++;
		}
	}
	for (int val : count)
		cout << val << endl;
}

int main()
{
	function();
	return 0;
}

发表于 2021-03-01 17:45:17 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main(){
    int i,j,n,q;
    unordered_map<string,int>m;//用于记录连续数字出现的数字,key=连续数字,value=次数
    cin>>n>>q;//n个手机号码,q个查询数字段
    unordered_set<string>phone;//用set进行存储避免了号码的重复插入
    string s;
    while(n--){        
        cin>>s;
        if(s.size()!=11)continue;//不是正确的电话号码则不必存储
        phone.insert(s);//用set进行插入,避免号码的重复
    }    
    for(unordered_set<string>::iterator it=phone.begin();it!=phone.end();++it){
        s=*it;
        unordered_set<string>c;
            for(i=0;i<11;++i){
                string t;
                for(j=i;j<11;++j){
                    t+=s[j];
                    c.insert(t);//将一个手机号码所有的连续组合方式进行存储,用空间替换时间
                }
            }
            for(auto p:c)m[p]++;//计数
    }    
    while(q--){
        cin>>s;//输入连续数字段
        cout<<m[s]<<endl;//输出他的次数
    }
    return 0;
}
注:直接用数学的查找方式if (phonenum[i].find(test) != string::npos)会超时,只能AC80%,这里用空间替换时间效率AC了100%。截取一个号码所有可能的连续组合方式,从而节约了find的时间。
发表于 2020-09-03 11:25:57 回复(0)
思路对了,编译也没报错,不知道怎么没输出。
#include<iostream>
#include<string>

using namespace std;

int main()
{
    int N,M;
    cin >> N >> M;
    string pnum[N];
    string fnum[M];
    int i=0;
    int j=0;
    int count = 0;
    int a;
    while(N--) //N = 3
    {
        
        cin >> pnum[i];
        i++;
    }
    while(M--)//M = 2
    {
        cin >> fnum[j];
        j++;
    }
    for(int p=0;p<M;p++)
    {
        for(int q=0;q<N;q++)
        {
            a = pnum[q].find(fnum[p]);
            if(a != -1)
            {
                count++;
            }
        }
        cout << count << endl;
    }
    
    return 0;
}


发表于 2020-08-25 18:38:18 回复(0)
#include<iostream>
(720)#include<string>
#include<vector>
using namespace std;
int main()
{
    unsigned int M, N;
    cin >> N;
    cin >> M;
    vector<string>Num;
    for (int i = 0; i < N; i++)
    {
        string temp;
        cin >> temp;
        Num.push_back(temp);
    }
    vector<string>Chack;
    for (int i = 0; i < M; i++)
    {
        string temp;
        cin >> temp;
        Chack.push_back(temp);
    }


    for (vector<string>::iterator it1=Chack.begin();it1!=Chack.end();it1++)
    {
        int out = 0;
        for (vector<string>::iterator it2 = Num.begin(); it2 != Num.end(); it2++)
        {
            int pos = (*it2).find((*it1));
            if (pos != -1)
            {
                out++;
            }
        }
        cout << out << endl;
    }
    return 0;
}

//超时 80%
发表于 2020-05-07 15:46:54 回复(0)
    private static void solution(String[] pNumbers,String[] tNumbers,int phoneNumbers,int targetNumbers) {
        int num =0;
        for (int i = 0; i < targetNumbers; i++) {
            for (int j = 0; j < phoneNumbers; j++) {
                if(pNumbers[j].contains(tNumbers[i]))
                    num++;
            }
            System.out.println(num);
            num=0;
        }
    }
这样写有个双重循环超时了,请问有别的方法解决问题吗?

发表于 2020-05-02 10:55:46 回复(0)

参考一下90%的代码吧(仅供参考

#include <bits/stdc++.h>

using namespace std;
unordered_map<string, int>buffmap;

int main()
{
    std::ios::sync_with_stdio(false);
    int N, count;cin >> N >> count;
    vector<string>buff(N, "");
    for (int i = 0; i < N; ++ i) {
        cin >> buff[i];
    }
    for (int i = 0; i < N; ++i) {
        unordered_set<string> buffset;
        for (int j = 0; j < buff[i].length(); ++j)
            for (int k = j; k < buff[i].length(); ++k)
                buffset.insert(buff[i].substr(j, k - j + 1));

        for (auto iter = buffset.begin(); iter != buffset.end(); ++iter) {
            buffmap[*iter] ++;
        }
    }
    while (count --) {
        string str; cin >> str;
        cout << buffmap[str] << endl;
    }
    return 0;
}
发表于 2020-05-01 10:52:34 回复(1)