2019.8.30 阿里巴巴算法岗笔试编程

1.题目描述:

自动语音识别(ASR)需要音频和文本的对应数据进行训练,但是通常我们无法直接拿到这样对应好的数据,因此需要一定的方法来构造。假设有一个句子列表1(长度为n),里面是既定的文本,我们要对每个文本构建一段对应的录音。方法是让录音人员一次性完成列表1中的文本的录音,规则是录完一条再录下一条。每条可能不止录一次,因为可能读错或读的不标准,所以对一条文本可再次尝试录音,最多可以再试x次,每次之间有停顿。然后对这个完整音频根据停顿切分成小音频,并对所有小音频进行语音识别(用当前ASR系统,这次识别会不太准)之后,得到列表2,长度最大为(x+1)*n,列表1和列表2都是有序的。现在要求对列表1中的每个元素,找到列表2中对应的元素(即文本相似度最高),使所有项的相似度的和最大(注意每个项的相似度最大不一定相似度的和最大),然后拿列表2中对应元素的音频作为既定文本的对应的录音。在相似度的和最大的基础上,对于既定的文本,我们倾向于选择录音人员最后一次说的比较好的录音,即尽量选择列表2中下标比较大的项。

为了简单起见,文本相似度采用 Jaccard距离进行计算,定义如下:

相似度 = s(i)和s(j)的交集的大小 / s(i)和s(j)的并集的大小,

其中s(i)和s(j)都是上述列表中的字符串,其交集是同时存在于二者中的字符组成的集合,并集是二者所有字符组成的集合。

那么你现在准备好为AI贡献自己的力量了吗?

输入输出:

编译器版本: gcc 4.8.4
请使用标准输入输出(stdin,stdout) ;请把所有程序写在一个文件里,勿使用已禁用图形、文件、网络、系统相关的头文件和操作,如sys/stat.h , unistd.h , curl/curl.h , process.h
时间限制: 3S (C/C++以外的语言为: 5 S) 内存限制: 128M (C/C++以外的语言为: 640 M)
输入:
输入数据有三行:
第一行是列表1,元素以英文逗号分隔
第二行是列表2,元素以英文逗号分隔
第三行是参数x
输出:
列表1中的每个元素对应列表2中的每个元素的下标,英文逗号分隔。

样例1:

输入:
床前明月光,疑是地上霜,举头望明月,低头思故乡
越光,床前地上霜,大地孤烟直,举头明月,低头是故乡
1
输出:
0,1,3,4

思路:

就,整呗,咱也不知道对不对

代码:

#include <iostream>
#include <vector>
#include <sstream>
#include <cstdio>
#include <map>

/*请完成下面这个函数,实现题目要求的功能*/
/*当然,你也可以不按照下面这个模板来作答,完全按照自己的想法来 ^-^ */
/******************************开始写代码******************************/
template < typename T > std::string to_string( const T& n )
{
    std::ostringstream stm ;
    stm << n ;
    return stm.str() ;
}
float cmp(std::string A,std::string B)
{
    float Jscore = 0.0,Bscore = 0.0;
    std::map<char,int> m;
    for(int i=0;i<A.size();i++)
    {
        if(m[A[i]] > 0)
            ;
        else
            m[A[i]]++,Bscore += 1;
    }
    for(int i=0;i<B.size();i++)
    {
        if(m[B[i]] > 0)
            Jscore += 1;
        else
            Bscore += 1;
    }
    return Jscore/Bscore;
}
std::string audioMatch(std::vector<std::string>& list1, std::vector<std::string>& list2, int x) {
    int now = 0;
    float most_cmp = 0;
    std::vector<int> res(list1.size()+1);
 //   for(int i=0;i
 //       std::cout<

    for(int i=0;i<list1.size();i++)
    {
        most_cmp = 0;
        int j;
        for(j=now;j<list2.size()&&j-now<=x;j++)
        {
            float score = cmp(list1.at(i),list2.at(j));
            if(i+1<list1.size())
                if(score < cmp(list1.at(i+1),list2.at(j)))
                    break;
            if(most_cmp<score)
            {
                res[i] = j;
                most_cmp = score;
            }
        }
        now = j;
    }
    std::string resS;
    for(int i=0;i<list1.size();i++)
    {
        resS += to_string(res[i]);
        if(i<list1.size()-1)
            resS += ',';
    }
    return resS;
}

/******************************结束写代码******************************/

void split(std::string& input_str, std::vector<std::string>& output_list) {
    std::istringstream tmp_stream(input_str);
    std::string tmp_str;
    while (getline(tmp_stream, tmp_str, ',')) {
        output_list.push_back(tmp_str);
    }
}

int main() {
    std::string s1;
    std::cin >> s1;

    std::string s2;
    std::cin >> s2;

    int x = 0;
    std::cin >> x;

    std::vector<std::string> list1;
    std::vector<std::string> list2;
    split(s1,list1);
    split(s2,list2);

    std::string res = audioMatch(list1, list2, x);
    std::cout << res << std::endl;

    return 0;
}


2.题目描述:

每天都有无数的人跟我厂出品的天猫精灵对话,天猫精灵为人类跟他说的每句话都打上了一个意图标签,一个人的所有对话就是这些意图标签组成的序列,这个序列里面的子序列就是一段对话,意图有查天气、查温度、查股票、放音乐、讲笑话等等。最近天猫精灵灵光一闪,想研究下人类的对话,看看人们都喜欢怎么和它说话,比如有的人喜欢先问天气,再问股票,再让它讲个笑话,再放首歌,有的人喜欢问了天气之后再问空气质量,然后再问下明天的天气,还有的人喜欢先听听歌,然后叫出租车去上班等等。天猫精灵要找出人们普遍的规律,分析出大家一般都喜欢怎么和他说话。那么首先天猫精灵必须先解决一个问题,就是给定两个用户的意图序列,找出相似(编辑距离 <= 阈值)的子意图序列的pair,并且每个子意图序列满足一定的长度要求(长度必须在闭区间 [minSeqLen, maxSeqLen] 内),一个子序列可重复出现在多个pair中。比如如下就是满足长度要求(长度区间 [5, 8])的两个相似(编辑距离为1,小于等于阈值2)的子意图序列pair:

A: weather, joke, music, stock, joke, joke, news

B: weather, joke, music, stock, joke, joke, texi

那么现在你可以帮天猫精灵完成这个任务吗?

输入输出:

编译器版本: gcc 4.8.4
请使用标准输入输出(stdin,stdout) ;请把所有程序写在一个文件里,勿使用已禁用图形、文件、网络、系统相关的头文件和操作,如sys/stat.h , unistd.h , curl/curl.h , process.h
时间限制: 3S (C/C++以外的语言为: 5 S) 内存限制: 128M (C/C++以外的语言为: 640 M)
输入:
输入数据包括五行:
第一行:一个数字,编辑距离阈值
第二行:一个数字,最小的序列长度
第三行:一个数字,最大的序列长度
第四行:用户A的意图序列,英文逗号分隔
第五行:用户B的意图序列,英文逗号分隔
输出:
一个数字,满足条件的意图序列的pair的个数

样例1:

输入:
1
3
5
weather,joke,music,stock,joke,news,taxi,temperature,pm2.5
joke,music,news,stock,joke,joke,news,taxi
输出:
14

思路:

先搞个编辑距离的函数出来,再暴力数呗,咱题目都看不懂,反正样例也没过

代码:

#include <iostream>
#include <vector>
#include <sstream>
#include <cmath>
#include <algorithm>
#include <cstdio>
using namespace std;

/*请完成下面这个函数,实现题目要求的功能*/
/*当然,你也可以不按照下面这个模板来作答,完全按照自己的想法来 ^-^ */
/******************************开始写代码******************************/
//算法
int ldistance(const string source, const string target)
{
	//step 1

	int n = source.length();
	int m = target.length();
	if (m == 0) return n;
	if (n == 0) return m;
	//Construct a matrix
	typedef vector< vector<int> >  Tmatrix;
	Tmatrix matrix(n + 1);
	for (int i = 0; i <= n; i++)  matrix[i].resize(m + 1);

	//step 2 Initialize

	for (int i = 1; i <= n; i++) matrix[i][0] = i;
	for (int i = 1; i <= m; i++) matrix[0][i] = i;

	//step 3
	for (int i = 1; i <= n; i++)
	{
		const char si = source[i - 1];
		//step 4
		for (int j = 1; j <= m; j++)
		{

			const char dj = target[j - 1];
			//step 5
			int cost;
			if (si == dj){
				cost = 0;
			}
			else{
				cost = 1;
			}
			//step 6
			const int above = matrix[i - 1][j] + 1;
			const int left = matrix[i][j - 1] + 1;
			const int diag = matrix[i - 1][j - 1] + cost;
			matrix[i][j] = min(above, min(left, diag));

		}
	}//step7
	return matrix[n][m];
}
int findSimilarPairs(int threshold, int minSeqLen, int maxSeqLen, std::vector<std::string>& list1, std::vector<std::string>& list2) {
    int res = 0;
    for(int i=0;i<list1.size();i++)
    {
        if(minSeqLen<=list1.at(i).length()&&list1.at(i).length()<=maxSeqLen)
            for(int j=0;j<list2.size();j++)
            {
                if(minSeqLen<=list2.at(j).length()&&list2.at(j).length()<=maxSeqLen)
                {
                    int dis = ldistance(list1.at(i),list2.at(j));
                    if(dis<=threshold)
                        res++;
                }


            }
    }
    return res;
}

/******************************结束写代码******************************/

void split(std::string& input_str, std::vector<std::string>& output_list) {
    std::istringstream tmp_stream(input_str);
    std::string tmp_str;
    while (getline(tmp_stream, tmp_str, ',')) {
        output_list.push_back(tmp_str);
    }
}

int main() {
    int threshold = 0;
    std::cin >> threshold;

    int minSeqLen = 0;
    std::cin >> minSeqLen;

    int maxSeqLen = 0;
    std::cin >> maxSeqLen;

    std::string s1;
    std::cin >> s1;

    std::string s2;
    std::cin >> s2;

    std::vector<std::string> list1;
    std::vector<std::string> list2;
    split(s1,list1);
    split(s2,list2);

    int res = findSimilarPairs(threshold, minSeqLen, maxSeqLen, list1, list2);
    std::cout << res << std::endl;

    return 0;
}

你可能感兴趣的:(2019.8.30 阿里巴巴算法岗笔试编程)