生成长字节数组而不重复给定大小的子数组

时间:2017-11-09 18:59:41

标签: java arrays algorithm

我想生成一个长字节数组,其中没有重复的大小为N的子序列。 N很小,通常在3到8之间。

显然生成一个任意长的数组是不可行的:大约2^(8*N)个字节之后会有2^(8*N)个子序列已经存在,所以不会有任何唯一的子序列可供使用(因为有2个) ^(8 * N)个大小为N的唯一字节序列。现在这是这种数组长度的上限,但不一定是下限。我不需要尽可能长的序列或类似的东西:N == 4的1,000,000个值可能就足够了,但至少应该可以检测序列在某些生成策略下何时对于唯一性来说太长。

理想情况下,生成策略很简单,就像在添加每个字节时检查每个先前的子序列一样。

我把Java用于具体,因为我现在正在使用它,但这个概念真的适用于任何语言。

1 个答案:

答案 0 :(得分:3)

用户harold in the comments进行的关键观察是,您可以创建最大序列,而无需重复de Bruijn sequence订单byte[] a的元素。

这样的序列(它们不是唯一的)包含每个可能的N元素子序列恰好一次,因此将是没有N元素重复子序列的最大序列。

剩下的问题是,是否可以相当简单地生成这些序列的前缀,答案是肯定的。

按照此blog post中描述的方法,可以按字典顺序生成大小为N或更小的所有Lyndon Words,并连接所有长度除以N + 1的所有N + 1以创建数组我们想要。

在Java中,字母表只是256字节值,上述链接的代码适用于处理固定长度的N,如下所示:

N == 2

这可以进一步优化,但它已经相对有效:它只使用少量的固定状态([0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, ..., 125, 0, 126, 0, 127, 0, -128, 0, -127, ..., 0, -3, 0, -2, 0, -1, 1, 1, 2, 1, 3, 1, 4, 1, 5, ...] 数组,其大小为0)加上有限的递归量(通常最多0, i, 0, i + 1, ...调用深度)和一些数学生成所有值"到位"。比保留所有看到1, i, 1, i + 1, ... - 序列的散列的解决方案要好得多重复数据删除!

对于好奇的,这里<?php define('DB_SERVER', 'xxx'); define('DB_USERNAME', 'xxx'); define('DB_PASSWORD', 'xxx'); define('DB_DATABASE', 'xxx'); $connection = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE); ?> 序列的第一位是什么样的:

<?php
require_once('Conexion.php');
$username = $_POST["Usuario"];
$passw = $_POST["Contrasena"];
$statement=mysqli_prepare($connection,"SELECT idTrabajador,`Nombre del Trabajador`,`Unidades por Vender`  FROM `tablausuario` WHERE `Usuario`=? AND Contrasena=?");
mysqli_stmt_bind_param($statement,"ss",$username,$passw);
mysqli_stmt_execute($statement);
mysqli_stmt_store_result($statement);
mysqli_stmt_bind_result($statement,$idTrabajador,$name,$uxv);
$response = array();
$response["success"] = false;
while(mysqli_stmt_fetch($statement)){
$response["success"] = true;
$response["idTrabajador"] = $idTrabajador;
$response["Nombre del Trabajador"] = $name;
$response["Unidades por Vender"] = $uxv;
}
echo json_encode($response);
mysqli_close($connection);
?>

所以protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); editUsuario = (EditText) findViewById(R.id.userLog); editPass = (EditText) findViewById(R.id.passLog); btnLogin = (Button) findViewById(R.id.btnLog); btnOlvide = (Button) findViewById(R.id.btnolvLog); img = (ImageView) findViewById(R.id.imgL); Display display = getWindowManager().getDefaultDisplay(); int heg = display.getHeight(); img.setMaxHeight(heg/3); btnLogin.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final String userPass = editPass.getText().toString(); final String userNam = editUsuario.getText().toString(); Response.Listener<String> responseListener = new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject jsonResponse = new JSONObject(response); boolean success = jsonResponse.getBoolean("success"); if (success) { String idTra = jsonResponse.getString("idTrabajador"); String naMe = jsonResponse.getString("Nombre del Trabajador"); //String uxv = jsonResponse.getString("Unidades por Vender"); Intent openLog = new Intent(LoginActivity.this, MenuPrincipal.class); openLog.putExtra("idTrabajador", idTra); openLog.putExtra("Nombre del Trabajador", naMe); LoginActivity.this.startActivity(openLog); } else { AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); builder.setMessage("Error de Login, Verifique su conexion o los datos ingresados") .setNegativeButton("Reintentar", null).create().show(); } } catch (JSONException e) { e.printStackTrace(); } } }; RequestLogin loginRequest = new RequestLogin(userNam, userPass, responseListener); RequestQueue queue = Volley.newRequestQueue(LoginActivity.this); queue.add(loginRequest); } }); 后跟一个简单的递增序列{{1}},后跟512个字节,然后是序列{{1}},依此类推。